docs: consolidate product roadmap and source docs

This commit is contained in:
a.tolmachev
2026-05-03 15:40:10 +00:00
parent 0f3ad2991e
commit c7b33930db
15 changed files with 1138 additions and 3077 deletions
+4
View File
@@ -18,6 +18,10 @@ Use the documents in this order when there is ambiguity:
8. `docs/development-rules.md`
9. `docs/rust-code-rules.md`
10. `docs/implementation-plan.md`
11. `docs/product-editions.md`
12. `docs/commercial-boundaries.md`
13. `docs/frontend-roadmap.md`
14. `docs/refactoring-roadmap.md`
If code and docs diverge, update docs first or together with code.
+314 -17
View File
@@ -2,30 +2,327 @@
## Current
### `feat/agent-scoped-machine-auth`
### `feat/community-agent-key-cutover`
Status: in_progress
Goal:
- довести открытую редакцию до продуктово завершенного машинного доступа через ключ AI-агента.
Main code areas:
- `crates/crank-core/src/agent.rs`
- `crates/crank-core/src/auth.rs`
- `crates/crank-registry/src/postgres/agent.rs`
- `crates/crank-registry/src/postgres/api_key.rs`
- `apps/admin-api/src/service.rs`
- `apps/admin-api/src/app.rs`
- `apps/mcp-server/src/app.rs`
- `apps/ui/js/agents.js`
- `apps/ui/js/api-keys.js`
- `apps/ui/html/agents.html`
- `apps/ui/html/api-keys.html`
- `apps/ui/js/i18n.js`
Implementation slices:
1. Закрыть remaining workspace/platform-key assumptions в `admin-api` и `mcp-server`.
2. Нормализовать list/create/revoke/delete flow для agent keys.
3. Привести UI страницы `Agents` и `API Keys` к одной модели agent-scoped machine access.
4. Явно ограничить `Community` на `security_level = standard`.
Progress:
- done: `mcp-server` принимает ключ только по `(workspace_slug, agent_slug, secret_hash)`;
- done: `admin-api` уже отдает и принимает agent-scoped key routes;
- done: UI `API Keys` переведен на agent-scoped machine access;
- done: removed legacy workspace-key routes, demo/bootstrap assumptions, and per-agent key count bug.
DoD:
- ключ создается и принадлежит конкретному AI-агенту;
- UI объясняет назначение ключа без ссылок на старую workspace-key модель;
- `mcp-server` принимает Community machine access только по agent key;
- Community flow не требует short-lived token service.
Verification:
- backend unit and integration tests for key lifecycle;
- MCP tool-call tests through agent endpoint;
- e2e smoke for agent key create/reveal/revoke.
## Next
### `feat/edition-capability-model`
Status: ready
DoD:
- AI agent can receive its own long-lived agent key from the admin UI
- operation has an explicit security level: `standard`, `elevated`, or `strict`
- machine calls to MCP can use short-lived agent tokens for elevated operations
- one-time token mode is defined for strict operations
- transition path from workspace-wide keys is explicit in docs and implementation slices
Goal:
- ввести capability model по редакциям и перестать смешивать Community и premium surface.
## Next
Main code areas:
- `crates/crank-core/src/*`
- `apps/admin-api/src/service.rs`
- `apps/admin-api/src/app.rs`
- `apps/ui/js/*`
- `apps/ui/html/*`
- `docs/product-editions.md`
- `docs/frontend-roadmap.md`
Implementation slices:
1. Ввести серверную модель capabilities:
- protocols
- auth modes
- security levels
- workspace/user/agent limits
2. Отдавать capability flags в `admin-api`.
3. Привести UI к capability gating вместо скрытых продуктовых допущений.
4. Зафиксировать Community defaults в docs и runtime config.
DoD:
- UI знает, какие функции входят в текущую редакцию;
- Community не показывает рабочие controls для premium-only features;
- capability checks существуют не только в UI, но и на сервере.
Verification:
- API tests for capability payloads;
- frontend smoke for hidden/locked states;
- manual verification on Community build.
### `feat/private-token-service-seam`
Status: ready
Goal:
- подготовить public codebase к private реализации короткоживущих и одноразовых токенов.
Main code areas:
- `crates/crank-core/src/auth.rs`
- `crates/crank-core/src/agent.rs`
- `apps/admin-api/src/app.rs`
- `apps/admin-api/src/service.rs`
- `apps/mcp-server/src/app.rs`
- `docs/agent-auth-model.md`
- `docs/admin-api.md`
- `docs/mcp-interface.md`
Implementation slices:
1. Определить stable contracts для:
- `POST /mcp-auth/v1/token`
- `POST /mcp-auth/v1/token/one-time`
2. Ввести abstraction для token verification в `mcp-server`.
3. Подготовить capability-gated UI/API surface без private implementation в Community.
4. Отделить Community `standard` flow от commercial `elevated/strict`.
DoD:
- public contracts зафиксированы и тестируемы;
- Community продолжает работать без private token service;
- premium auth paths не размазываются по Community logic.
Verification:
- contract tests for auth payload shapes;
- unit tests for credential-kind enforcement;
- docs sync check.
### `feat/community-surface-trim`
Status: ready
Goal:
- привести открытую редакцию к честному product surface и убрать расхождение между текущим кодом и edition policy.
Main code areas:
- `apps/ui/js/wizard.js`
- `apps/ui/js/wizard-model.js`
- `apps/ui/js/agents.js`
- `apps/ui/js/settings.js`
- `apps/ui/js/i18n.js`
- `docs/product-editions.md`
- `docs/architecture.md`
- `docs/mcp-interface.md`
Implementation slices:
1. Скрыть или честно заблокировать:
- `WebSocket`
- `SOAP`
- `gRPC streaming`
- streaming execution modes
- `elevated/strict` security levels
в Community.
2. Привести copy и feature affordances к open-core границе.
3. Добавить edition-aware explanation в wizard и agents UI.
DoD:
- Community UX не создает ложного ожидания наличия premium functionality;
- protocol set и security levels совпадают в docs, UI и runtime contracts.
Verification:
- e2e checks for wizard protocol list;
- manual Community smoke;
- localized copy review.
## Planned
### `feat/frontend-commercial-polish`
Status: ready
Goal:
- закрыть оставшиеся UI/UX дефекты, мешающие коммерческой демонстрации и продажной версии продукта.
Main code areas:
- `apps/ui/js/api-keys.js`
- `apps/ui/js/agents.js`
- `apps/ui/js/secrets.js`
- `apps/ui/js/usage.js`
- `apps/ui/js/settings.js`
- `apps/ui/js/workspace-setup.js`
- `apps/ui/js/auth.js`
- `apps/ui/css/*`
- `docs/frontend-roadmap.md`
Implementation slices:
1. Перевести mobile tables в card layouts для:
- `API Keys`
- `Secrets`
- `Usage`
2. Доделать `Agents` page и modal:
- объяснение отдельных agent endpoints
- empty states
- slug hints
3. Добить `Settings` and workspace flows:
- terminology cleanup
- navigation spacing
- notifications honesty
- mobile sticky bug
4. Довести agent-key UX на `API Keys` page.
DoD:
- mobile UI не требует обязательного горизонтального скролла для primary actions;
- terminology и product copy согласованы;
- коммерческая демонстрация проходит без UI contradictions.
Verification:
- targeted Playwright coverage;
- manual mobile checks at 375px width;
- EN/RU copy audit.
### `feat/open-core-repo-boundary`
Status: ready
Goal:
- закрепить техническую границу между public Community repo и private commercial delivery.
Main code areas:
- `docs/commercial-boundaries.md`
- `docs/module-decomposition.md`
- `docs/development-rules.md`
- `docs/implementation-plan.md`
- release scripts / Docker manifests / future packaging files
Implementation slices:
1. Определить extension seams в public code.
2. Подготовить отдельные delivery manifests для Community.
3. Убрать из public repo assumptions о размещении private code рядом с Community logic.
4. Подготовить naming и packaging strategy для private repositories.
DoD:
- можно объяснить, что именно публикуется как OSS, а что уходит в private delivery;
- Community release path отделен от commercial release path;
- документация не ссылается на удаленные review files.
Verification:
- docs consistency pass;
- release checklist review.
### `feat/enterprise-access-governance`
Status: ready
Goal:
- реализовать enterprise access layer вне Community scope.
Main code areas:
- private `enterprise` services and crates
- public contracts in:
- `docs/admin-api.md`
- `docs/agent-auth-model.md`
- `docs/product-editions.md`
Implementation slices:
1. `SSO`
2. `2FA`
3. extended `RBAC`
4. `audit log`
5. enterprise admin flows in UI through capability gating
DoD:
- governance features не живут как полумеры в Community;
- enterprise access model согласован с public contracts.
### `feat/cloud-metering-control-plane`
Status: ready
Goal:
- подготовить hosted-редакцию как отдельный продуктовый контур.
Main code areas:
- private cloud services
- usage/metering integration points
- `docs/product-editions.md`
- `docs/commercial-boundaries.md`
Implementation slices:
1. usage metering by workspace / agent / token;
2. billing integration;
3. hosted tenant controls;
4. cloud operational tooling.
DoD:
- Cloud edition не зависит от ручного учета usage;
- hosted product surface согласован с feature matrix.
### `feat/release-protection-distribution`
Status: ready
Goal:
- подготовить безопасную поставку Community и коммерческих редакций.
Main code areas:
- CI workflows
- Dockerfiles
- deployment manifests
- release docs
Implementation slices:
1. public GitHub release flow for Community;
2. private registry flow for Enterprise;
3. signed artifacts and provenance;
4. release checklist for edition-specific packaging.
DoD:
- Community публикуется из public repo;
- Enterprise и Cloud используют private delivery path;
- коммерческий код не требуется публиковать в open source ради поставки.
### `feat/live-authenticated-staging-entry`
Status: ready
Goal:
- держать реальный staging/demo контур в состоянии, пригодном для демонстрации и регрессии.
Main code areas:
- `docs/demo-runbook.md`
- `docs/deploy-and-staging-smoke.md`
- `docs/authenticated-staging-pass.md`
- deployment workflows
Implementation slices:
1. актуализировать demo user flow;
2. прогнать authenticated staging pass;
3. зафиксировать regressions и manual checks;
4. синхронизировать deploy docs с реальным окружением.
DoD:
- authenticated staging flow runs against the real deployed environment
- operator docs match the current deploy/runtime model
- staging validation is captured without relying on local fixtures
## Completed
- `feat/websocket-test-run-polish`
- `feat/frontend-wizard-modularization`
- `feat/distributed-mcp-session-store`
- staging validation не зависит от локальных фикстур;
- documentation matches deployed behavior;
- demo flow reproducible on real environment.
-1333
View File
File diff suppressed because it is too large Load Diff
-832
View File
@@ -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
View File
@@ -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.
+4
View File
@@ -143,6 +143,8 @@ AI-агент не должен:
- статический ключ AI-агента как режим совместимости;
- короткоживущие токены по OAuth 2.0 как рекомендуемый режим.
Реализация этого режима должна рассматриваться как коммерческий контур и не должна требовать размещения private token-issuer logic в public repository.
Соответственно, платформа может обслуживать операции уровня:
- `standard`;
@@ -156,6 +158,8 @@ AI-агент не должен:
- короткоживущий токен;
- одноразовый токен.
Enterprise-реализация должна поставляться через private delivery и опираться на capability-gated integrations в public codebase.
Соответственно, допускаются операции уровня:
- `standard`;
+22
View File
@@ -218,6 +218,28 @@ Crank - платформа для публикации внешних API в в
- request headers
- operation template
- variables mapping
## 8. Open-core граница
Crank развивается как open-core продукт.
Это означает:
- `Community` должна полностью собираться из этого репозитория;
- коммерческие возможности не должны храниться здесь как рабочий private code;
- различия между редакциями должны отражаться в capability model, API, UI и delivery pipeline.
Ключевые продуктовые различия зафиксированы в `docs/product-editions.md`.
## 9. Коммерческий контур
Коммерческий контур не должен защищаться "скрытием" уже опубликованного исходного кода. Правильная архитектурная граница выглядит так:
- в public repo остается Community runtime и extension seams;
- коммерческие реализации поставляются из private repositories или private artifacts;
- критичные правила лицензирования, metering и token issuance исполняются на серверной стороне.
Практические правила зафиксированы в `docs/commercial-boundaries.md`.
- извлечение результата из `data`
GraphQL в MCP публикуется как фиксированная операция с предсказуемой структурой ответа.
+196
View File
@@ -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`
+9
View File
@@ -174,6 +174,15 @@
- домен не знает про HTTP, SQL, storage и transport;
- adapters и repositories реализуют контракты, заданные ближе к домену.
## 7.4. Open-core правило
Для проекта фиксируется дополнительное правило:
- код `Community` живет в public repository;
- коммерческий код не должен попадать в public repository "на будущее";
- в public code допустимы только extension seams, capability flags и контракты для private implementations;
- edition gating должно проверяться на серверной стороне, а не только в UI.
## 8. Git workflow
## 8.1. Remote
+133
View File
@@ -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
View File
@@ -2,217 +2,168 @@
## 1. Назначение документа
Этот документ фиксирует порядок перехода от текущего состояния проекта к целевой product-ready integration platform модели.
Этот документ фиксирует актуальный порядок подготовки Crank к коммерческой реализации как open-core продукта.
Документ не повторяет уже выполненные исторические этапы. Он описывает только тот план, по которому проект должен двигаться дальше.
## 2. Базовый принцип
Работа делится на два контура:
1. завершение и hardening открытой редакции `Community`;
2. подготовка архитектурных, продуктовых и delivery-границ для `Enterprise` и `Cloud`.
Принцип:
- сначала перепроектирование `as is -> to be`;
- потом foundation под workspace/agent model;
- потом возврат к end-to-end UI сценариям;
- потом observability и access layer;
- потом polish и demo readiness;
- потом расширение до полного protocol platform scope.
- сначала нужно сделать честную и законченную `Community`-основу;
- затем нужно отделить commercial seams и private delivery;
- только после этого имеет смысл реализовывать коммерческие расширения.
## 2. Этап 1. Перепроектирование `As Is -> To Be`
## 3. Этап 1. Open-core product boundary
Цель:
### Цель
- зафиксировать новую доменную модель и page-driven backend contract.
Зафиксировать, что входит в `Community`, а что уходит в `Enterprise` и `Cloud`.
DoD:
### DoD
- зафиксирован `as is -> to be` план;
- page-by-page gap analysis покрывает все целевые экраны;
- разобраны все архитектурные конфликты UI vs current backend;
- документы `architecture`, `data-model`, `database-schema`, `admin-api`, `mcp-interface` синхронизированы.
- документы `product-editions`, `commercial-boundaries`, `architecture`, `module-decomposition` синхронизированы;
- в кодовой базе определена capability model по редакциям;
- UI и API не обещают Community-функции, которых там не должно быть;
- старые review-файлы не требуются как отдельный источник истины.
## 3. Этап 2. Workspace foundation
## 4. Этап 2. Community machine access completion
Цель:
### Цель
- перевести хранение и API на workspace-scoped модель.
Довести базовую модель машинного доступа Community до полностью рабочего состояния.
DoD:
### DoD
- операции и auth profiles принадлежат workspace;
- registry умеет фильтровать данные по workspace;
- есть default workspace migration path.
- у AI-агента есть собственный ключ;
- UI умеет выпускать, показывать, отзывать и удалять agent keys;
- `mcp-server` использует agent-scoped machine access;
- Community поддерживает только `security_level = standard`;
- в системе не остается product-facing assumptions про workspace-wide machine key как основной способ вызова.
## 4. Этап 3. Agent publishing foundation
## 5. Этап 3. Edition capability model
Цель:
### Цель
- ввести `Agent` и agent-scoped MCP publishing.
Подготовить инфраструктуру, которая позволит одной кодовой базе честно различать редакции продукта.
DoD:
### DoD
- можно создать agent и привязать к нему published operations;
- `mcp-server` выдает tools в контексте конкретного agent;
- один agent видит только свой curated toolset.
- существует server-side capability model:
- protocols
- auth modes
- security levels
- workspace/user limits
- `admin-api` возвращает capability flags для UI;
- UI скрывает или честно блокирует premium functionality;
- Community build не содержит ложных "почти доступных" product paths.
## 5. Этап 4. Operations and wizard integration
## 6. Этап 4. Private auth-service seam
Цель:
### Цель
- посадить operations catalog и wizard на реальные backend contracts.
Подготовить публичный код к private реализации короткоживущих и одноразовых токенов.
DoD:
### DoD
- каталог операций и wizard работают без `localStorage` overrides;
- operation edit/delete/publish/test выполняются через backend;
- все протоколы работают в рамках одного UI flow.
- зафиксированы контракты для:
- `POST /mcp-auth/v1/token`
- `POST /mcp-auth/v1/token/one-time`
- в `mcp-server` существует abstraction для проверки токенов;
- `admin-api` и `mcp-interface` знают про эти контракты документированно;
- Community при этом остается полностью работоспособной без private token service.
## 6. Этап 5. Agents UI and backend
## 7. Этап 5. Commercial protocol split
Цель:
### Цель
- реализовать agent-centric слой.
Перестать считать весь текущий protocol surface частью открытой редакции.
DoD:
### DoD
- agent CRUD работает;
- binding operations к agent работает;
- published agent появляется в MCP runtime.
- определен canonical Community protocol set;
- premium protocol families и premium execution modes вынесены в коммерческий план;
- UI capability-gated по протоколам;
- release model для Community не требует shipping premium flow как рабочей open-source функции.
## 7. Этап 6. Agent-scoped machine access
## 8. Этап 6. Frontend launch readiness
Цель:
### Цель
- реализовать machine access на уровне AI-агента и ввести обязательный уровень защиты операции.
Довести UI до коммерчески пригодного состояния для `Community` и подготовить edition-aware product surface.
DoD:
### DoD
- UI умеет выпускать и отзывать ключи конкретного AI-агента;
- длинноживущий машинный доступ больше не описывается ключом рабочей области;
- у операции появляется обязательный `security_level`;
- machine access не смешивается с upstream auth profiles;
- Community поддерживает базовый режим со статическим ключом AI-агента.
- agent key UX доведен до продукта;
- mobile layouts для data-heavy страниц больше не ломают primary actions;
- terminology и localization согласованы;
- settings и workspace flows не содержат misleading или half-functional sections;
- UI понимает разницу между Community и premium capabilities.
## 8. Этап 7. Token exchange and short-lived auth
## 9. Этап 7. Enterprise access and governance
Цель:
### Цель
- внедрить расширенные режимы доступа для операций повышенной чувствительности.
Реализовать коммерческий access/governance слой в private delivery.
DoD:
### DoD
- существует конечная точка выдачи токена по ключу агента;
- есть модель одноразового токена для чувствительных вызовов;
- токены ограничены по сроку жизни, области действия и числу использований;
- операции уровня `elevated` нельзя вызвать по статическому ключу;
- операции уровня `strict` можно вызвать только по одноразовому токену.
- есть `SSO`;
- есть `2FA`;
- есть расширенная `RBAC`;
- есть `audit log`;
- существует private delivery path для self-hosted customers.
## 9. Этап 8. Observability
## 10. Этап 8. Cloud control plane
Цель:
### Цель
- реализовать логи и usage.
Подготовить hosted-редакцию как отдельный продуктовый контур.
DoD:
### DoD
- `Logs` page и `Usage` page работают на реальных данных;
- есть продуктовые endpoints, а не только application logs;
- rollups и detail views согласованы с UI.
- есть metering;
- есть billing integration;
- есть hosted tenant model;
- есть cloud deployment and support tooling;
- capability model синхронизирована с hosted plans.
## 10. Этап 9. Alpine UI integration
## 11. Этап 9. Release and distribution hardening
Цель:
### Цель
- довести `apps/ui` до полной работы на реальном backend.
Подготовить безопасную поставку открытой и коммерческой редакций.
DoD:
### DoD
- `apps/ui` содержит целевой Alpine.js UI;
- mock JSON больше не используется на критическом пути;
- UI, backend и docs синхронизированы.
- Community публикуется из public GitHub repository;
- Enterprise поставляется через private container registry и private manifests;
- Cloud использует отдельный private operational contour;
- build provenance и подпись артефактов документированы;
- коммерческий код не требуется публиковать в public repository.
## 11. Этап 10. Secret store and upstream auth
## 12. Этап 10. Live staging and demo readiness
Цель:
### Цель
- заменить UI placeholder-модель `${secrets.*}` на рабочий backend/runtime слой secrets.
Поддерживать реальный стенд и демонстрационный сценарий в состоянии, пригодном для продажи и демонстрации.
DoD:
### DoD
- есть workspace-scoped `Secrets` resource;
- secret values хранятся только в зашифрованном виде;
- `AuthProfile` ссылается на `secret_id`, а не на строковый placeholder;
- runtime умеет применять bearer/basic/api-key auth к реальному upstream request;
- wizard имеет auth selector и quick-create flow для secrets/auth profiles.
- live authenticated staging pass воспроизводим;
- deploy smoke и operator docs совпадают с реальной поставкой;
- demo user flow подтвержден на реальном окружении;
- регрессии в publish/call/auth flow ловятся до релиза.
## 12. Этап 11. Hardening and demo readiness
## 13. Связанные документы
Цель:
- довести продукт до стабильного демо-сценария.
DoD:
- end-to-end demo воспроизводим;
- deployment и healthchecks стабильно зелёные;
- документация и продуктовый сценарий совпадают.
## 13. Этап 12. MCP streaming proxy support
Цель:
- довести Crank до controlled streaming model поверх MCP `Streamable HTTP`.
DoD:
- `mcp-server` соответствует transport semantics `2025-06-18`;
- execution modes `window`, `session`, `async_job` формально описаны и реализованы;
- REST SSE и gRPC server-streaming поддерживаются в bounded форме;
- UI умеет конфигурировать streaming limits, aggregation и lifecycle;
- e2e сценарии покрывают window/session/job calls.
## 14. Этап 13. WebSocket upstream support
Цель:
- добавить полноценный WebSocket upstream adapter в общую execution model.
DoD:
- есть WebSocket target model;
- runtime поддерживает bounded `window`, `session` и `async_job`;
- heartbeat, reconnect и subscription lifecycle конфигурируются явно;
- docs, UI и e2e синхронизированы.
## 15. Этап 14. SOAP support
Цель:
- добавить SOAP как enterprise-oriented protocol family.
DoD:
- есть WSDL/XSD-driven target model;
- runtime умеет строить SOAP envelopes и нормализовать SOAP Faults;
- operator может выбрать service, port и operation;
- test-run, publish и observability работают так же, как для остальных протоколов.
## 16. Этап 15. Detailed streaming specs
Цель:
- довести streaming-docs до function-level и field-level design спецификации.
DoD:
- есть отдельные docs для streaming admin-api, runtime, UI и capability matrix;
- protocol docs не противоречат общей execution model;
- roadmap и `TASKS.md` синхронизированы с full-detail architecture.
## 17. Этап 16. Streaming implementation slices
Цель:
- перевести streaming design в agent-friendly execution plan по файлам, тестам и DoD.
DoD:
- есть отдельный implementation spec по всем streaming slices;
- указаны file-level changes;
- указаны обязательные тесты и acceptance criteria;
- state transitions и sequence outlines зафиксированы явно.
- `docs/product-editions.md`
- `docs/commercial-boundaries.md`
- `docs/frontend-roadmap.md`
- `docs/refactoring-roadmap.md`
- `docs/agent-auth-model.md`
+5
View File
@@ -110,6 +110,11 @@
- операция задает обязательный `security_level`, и `mcp-server` обязан отклонять вызов, если представленный credential слабее требуемого уровня;
- детальная модель уровней зафиксирована в `docs/agent-auth-model.md`.
Важно:
- Community-сборка должна работать полностью без private token services;
- commercial token flows должны подключаться через capability-gated server-side integrations.
Уровни защиты операции:
- `standard`
+38
View File
@@ -159,3 +159,41 @@
Антипаттерн:
не превращать `mcp-server` во второй `admin-api`.
## 5. Разделение open-source и commercial модулей
### 5.1. Что остается в public repository
В этом репозитории должны жить:
- Community domain model;
- Community runtime;
- Community UI;
- extension seams для коммерческих возможностей;
- capability model по редакциям.
### 5.2. Что должно выноситься в private delivery
За пределами public repo должны жить:
- short-lived и one-time token issuers;
- enterprise access services;
- `SSO`, `2FA`, `RBAC`, `audit log`;
- metering и billing;
- cloud control plane;
- premium protocol families, если они не входят в Community edition.
### 5.3. Техническое правило
Public code не должен содержать скрытую private business logic.
Допустимо:
- trait boundaries;
- capability flags;
- edition-aware service contracts.
Недопустимо:
- полноценная коммерческая реализация в open-source исходниках;
- UI, который реально включает premium flow без server-side gating.
+192
View File
@@ -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`
+111
View File
@@ -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.