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`
|
8. `docs/development-rules.md`
|
||||||
9. `docs/rust-code-rules.md`
|
9. `docs/rust-code-rules.md`
|
||||||
10. `docs/implementation-plan.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.
|
If code and docs diverge, update docs first or together with code.
|
||||||
|
|
||||||
|
|||||||
@@ -2,30 +2,327 @@
|
|||||||
|
|
||||||
## Current
|
## 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
|
Status: ready
|
||||||
|
|
||||||
DoD:
|
Goal:
|
||||||
- AI agent can receive its own long-lived agent key from the admin UI
|
- ввести capability model по редакциям и перестать смешивать Community и premium surface.
|
||||||
- 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
|
|
||||||
|
|
||||||
## 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`
|
### `feat/live-authenticated-staging-entry`
|
||||||
|
|
||||||
Status: ready
|
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:
|
DoD:
|
||||||
- authenticated staging flow runs against the real deployed environment
|
- staging validation не зависит от локальных фикстур;
|
||||||
- operator docs match the current deploy/runtime model
|
- documentation matches deployed behavior;
|
||||||
- staging validation is captured without relying on local fixtures
|
- demo flow reproducible on real environment.
|
||||||
|
|
||||||
## Completed
|
|
||||||
|
|
||||||
- `feat/websocket-test-run-polish`
|
|
||||||
- `feat/frontend-wizard-modularization`
|
|
||||||
- `feat/distributed-mcp-session-store`
|
|
||||||
|
|||||||
-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-агента как режим совместимости;
|
- статический ключ AI-агента как режим совместимости;
|
||||||
- короткоживущие токены по OAuth 2.0 как рекомендуемый режим.
|
- короткоживущие токены по OAuth 2.0 как рекомендуемый режим.
|
||||||
|
|
||||||
|
Реализация этого режима должна рассматриваться как коммерческий контур и не должна требовать размещения private token-issuer logic в public repository.
|
||||||
|
|
||||||
Соответственно, платформа может обслуживать операции уровня:
|
Соответственно, платформа может обслуживать операции уровня:
|
||||||
|
|
||||||
- `standard`;
|
- `standard`;
|
||||||
@@ -156,6 +158,8 @@ AI-агент не должен:
|
|||||||
- короткоживущий токен;
|
- короткоживущий токен;
|
||||||
- одноразовый токен.
|
- одноразовый токен.
|
||||||
|
|
||||||
|
Enterprise-реализация должна поставляться через private delivery и опираться на capability-gated integrations в public codebase.
|
||||||
|
|
||||||
Соответственно, допускаются операции уровня:
|
Соответственно, допускаются операции уровня:
|
||||||
|
|
||||||
- `standard`;
|
- `standard`;
|
||||||
|
|||||||
@@ -218,6 +218,28 @@ Crank - платформа для публикации внешних API в в
|
|||||||
- request headers
|
- request headers
|
||||||
- operation template
|
- operation template
|
||||||
- variables mapping
|
- 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`
|
- извлечение результата из `data`
|
||||||
|
|
||||||
GraphQL в MCP публикуется как фиксированная операция с предсказуемой структурой ответа.
|
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;
|
- домен не знает про HTTP, SQL, storage и transport;
|
||||||
- adapters и repositories реализуют контракты, заданные ближе к домену.
|
- 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. Git workflow
|
||||||
|
|
||||||
## 8.1. Remote
|
## 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. Назначение документа
|
## 1. Назначение документа
|
||||||
|
|
||||||
Этот документ фиксирует порядок перехода от текущего состояния проекта к целевой product-ready integration platform модели.
|
Этот документ фиксирует актуальный порядок подготовки Crank к коммерческой реализации как open-core продукта.
|
||||||
|
|
||||||
|
Документ не повторяет уже выполненные исторические этапы. Он описывает только тот план, по которому проект должен двигаться дальше.
|
||||||
|
|
||||||
|
## 2. Базовый принцип
|
||||||
|
|
||||||
|
Работа делится на два контура:
|
||||||
|
|
||||||
|
1. завершение и hardening открытой редакции `Community`;
|
||||||
|
2. подготовка архитектурных, продуктовых и delivery-границ для `Enterprise` и `Cloud`.
|
||||||
|
|
||||||
Принцип:
|
Принцип:
|
||||||
|
|
||||||
- сначала перепроектирование `as is -> to be`;
|
- сначала нужно сделать честную и законченную `Community`-основу;
|
||||||
- потом foundation под workspace/agent model;
|
- затем нужно отделить commercial seams и private delivery;
|
||||||
- потом возврат к end-to-end UI сценариям;
|
- только после этого имеет смысл реализовывать коммерческие расширения.
|
||||||
- потом observability и access layer;
|
|
||||||
- потом polish и demo readiness;
|
|
||||||
- потом расширение до полного protocol platform scope.
|
|
||||||
|
|
||||||
## 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` план;
|
- документы `product-editions`, `commercial-boundaries`, `architecture`, `module-decomposition` синхронизированы;
|
||||||
- page-by-page gap analysis покрывает все целевые экраны;
|
- в кодовой базе определена capability model по редакциям;
|
||||||
- разобраны все архитектурные конфликты UI vs current backend;
|
- UI и API не обещают Community-функции, которых там не должно быть;
|
||||||
- документы `architecture`, `data-model`, `database-schema`, `admin-api`, `mcp-interface` синхронизированы.
|
- старые review-файлы не требуются как отдельный источник истины.
|
||||||
|
|
||||||
## 3. Этап 2. Workspace foundation
|
## 4. Этап 2. Community machine access completion
|
||||||
|
|
||||||
Цель:
|
### Цель
|
||||||
|
|
||||||
- перевести хранение и API на workspace-scoped модель.
|
Довести базовую модель машинного доступа Community до полностью рабочего состояния.
|
||||||
|
|
||||||
DoD:
|
### DoD
|
||||||
|
|
||||||
- операции и auth profiles принадлежат workspace;
|
- у AI-агента есть собственный ключ;
|
||||||
- registry умеет фильтровать данные по workspace;
|
- UI умеет выпускать, показывать, отзывать и удалять agent keys;
|
||||||
- есть default workspace migration path.
|
- `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;
|
- существует server-side capability model:
|
||||||
- `mcp-server` выдает tools в контексте конкретного agent;
|
- protocols
|
||||||
- один agent видит только свой curated toolset.
|
- 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;
|
- `POST /mcp-auth/v1/token`
|
||||||
- все протоколы работают в рамках одного UI flow.
|
- `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 работает;
|
- определен canonical Community protocol set;
|
||||||
- binding operations к agent работает;
|
- premium protocol families и premium execution modes вынесены в коммерческий план;
|
||||||
- published agent появляется в MCP runtime.
|
- 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-агента;
|
- agent key UX доведен до продукта;
|
||||||
- длинноживущий машинный доступ больше не описывается ключом рабочей области;
|
- mobile layouts для data-heavy страниц больше не ломают primary actions;
|
||||||
- у операции появляется обязательный `security_level`;
|
- terminology и localization согласованы;
|
||||||
- machine access не смешивается с upstream auth profiles;
|
- settings и workspace flows не содержат misleading или half-functional sections;
|
||||||
- Community поддерживает базовый режим со статическим ключом AI-агента.
|
- UI понимает разницу между Community и premium capabilities.
|
||||||
|
|
||||||
## 8. Этап 7. Token exchange and short-lived auth
|
## 9. Этап 7. Enterprise access and governance
|
||||||
|
|
||||||
Цель:
|
### Цель
|
||||||
|
|
||||||
- внедрить расширенные режимы доступа для операций повышенной чувствительности.
|
Реализовать коммерческий access/governance слой в private delivery.
|
||||||
|
|
||||||
DoD:
|
### DoD
|
||||||
|
|
||||||
- существует конечная точка выдачи токена по ключу агента;
|
- есть `SSO`;
|
||||||
- есть модель одноразового токена для чувствительных вызовов;
|
- есть `2FA`;
|
||||||
- токены ограничены по сроку жизни, области действия и числу использований;
|
- есть расширенная `RBAC`;
|
||||||
- операции уровня `elevated` нельзя вызвать по статическому ключу;
|
- есть `audit log`;
|
||||||
- операции уровня `strict` можно вызвать только по одноразовому токену.
|
- существует private delivery path для self-hosted customers.
|
||||||
|
|
||||||
## 9. Этап 8. Observability
|
## 10. Этап 8. Cloud control plane
|
||||||
|
|
||||||
Цель:
|
### Цель
|
||||||
|
|
||||||
- реализовать логи и usage.
|
Подготовить hosted-редакцию как отдельный продуктовый контур.
|
||||||
|
|
||||||
DoD:
|
### DoD
|
||||||
|
|
||||||
- `Logs` page и `Usage` page работают на реальных данных;
|
- есть metering;
|
||||||
- есть продуктовые endpoints, а не только application logs;
|
- есть billing integration;
|
||||||
- rollups и detail views согласованы с UI.
|
- есть 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;
|
- Community публикуется из public GitHub repository;
|
||||||
- mock JSON больше не используется на критическом пути;
|
- Enterprise поставляется через private container registry и private manifests;
|
||||||
- UI, backend и docs синхронизированы.
|
- 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;
|
- live authenticated staging pass воспроизводим;
|
||||||
- secret values хранятся только в зашифрованном виде;
|
- deploy smoke и operator docs совпадают с реальной поставкой;
|
||||||
- `AuthProfile` ссылается на `secret_id`, а не на строковый placeholder;
|
- demo user flow подтвержден на реальном окружении;
|
||||||
- runtime умеет применять bearer/basic/api-key auth к реальному upstream request;
|
- регрессии в publish/call/auth flow ловятся до релиза.
|
||||||
- wizard имеет auth selector и quick-create flow для secrets/auth profiles.
|
|
||||||
|
|
||||||
## 12. Этап 11. Hardening and demo readiness
|
## 13. Связанные документы
|
||||||
|
|
||||||
Цель:
|
- `docs/product-editions.md`
|
||||||
|
- `docs/commercial-boundaries.md`
|
||||||
- довести продукт до стабильного демо-сценария.
|
- `docs/frontend-roadmap.md`
|
||||||
|
- `docs/refactoring-roadmap.md`
|
||||||
DoD:
|
- `docs/agent-auth-model.md`
|
||||||
|
|
||||||
- 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 зафиксированы явно.
|
|
||||||
|
|||||||
@@ -110,6 +110,11 @@
|
|||||||
- операция задает обязательный `security_level`, и `mcp-server` обязан отклонять вызов, если представленный credential слабее требуемого уровня;
|
- операция задает обязательный `security_level`, и `mcp-server` обязан отклонять вызов, если представленный credential слабее требуемого уровня;
|
||||||
- детальная модель уровней зафиксирована в `docs/agent-auth-model.md`.
|
- детальная модель уровней зафиксирована в `docs/agent-auth-model.md`.
|
||||||
|
|
||||||
|
Важно:
|
||||||
|
|
||||||
|
- Community-сборка должна работать полностью без private token services;
|
||||||
|
- commercial token flows должны подключаться через capability-gated server-side integrations.
|
||||||
|
|
||||||
Уровни защиты операции:
|
Уровни защиты операции:
|
||||||
|
|
||||||
- `standard`
|
- `standard`
|
||||||
|
|||||||
@@ -159,3 +159,41 @@
|
|||||||
Антипаттерн:
|
Антипаттерн:
|
||||||
|
|
||||||
не превращать `mcp-server` во второй `admin-api`.
|
не превращать `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