From 0c10316479a6947a3614ef52c8cf378779b0f637 Mon Sep 17 00:00:00 2001 From: leemour Date: Sun, 4 Oct 2026 12:13:22 +0200 Subject: [PATCH 1/5] docs(plans): architecture guide, shared security page and footer links Plan for review: a shared architecture guide with per-language diagrams, a shared security page that the tg and max pages point to, and footer links to the support chat and that page. Co-Authored-By: Claude Opus 5.5 (1M context) --- .../2026-10-04-architecture-and-security.md | 153 ++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 docs/plans/2026-10-04-architecture-and-security.md diff --git a/docs/plans/2026-10-04-architecture-and-security.md b/docs/plans/2026-10-04-architecture-and-security.md new file mode 100644 index 0000000..8ebeb57 --- /dev/null +++ b/docs/plans/2026-10-04-architecture-and-security.md @@ -0,0 +1,153 @@ +# Architecture guide, shared security page, footer links + +The owner asked for three things on 2026-10-04: + +1. A public architecture guide for users and contributors: the packages (cli-core, cli-messaging, + its SQLite and ONNX builds, the two CLIs), the layers in the code, how adapters work, the key + patterns. Diagrams. It shows how things work and where the limits are; it does not sell. +2. Footer: "Report a problem" leads to the support Telegram chat; "Security" leads to a shared + security page, not to tg's. +3. A shared security page on the site, and the tg and max security pages pointing to it, each + keeping its own details. + +## Current state (origin/main, 2026-10-04) + +Sources read: cli-docs `a4c1899`, cli-messaging `680d22e` (0.140.0), cli-core 0.17.0, max-cli +`b09b0ca` (pins cli-messaging 0.140.0), tg-cli `4a36e85`. + +**Architecture material that exists, none of it on the site:** + +- `cli-messaging/docs/dev/ARCHITECTURE.md` (307 lines) — modules, store, migrations, the command + skeleton, the five layers, services. Its "Who consumes it" section says max's personal account + keeps its own cache; that has not been true since the T6 cache-off work (max-cli #330–#344). +- `cli-messaging/docs/dev/ADAPTERS.md` (187 lines) — the adapter contract: required core, optional + groups through `capability()`, ids as strings, `sendId` and `outcome_unknown`, + `history: "server" | "store"`, contract cases. +- `max-cli/docs/dev/ARCHITECTURE.md` (560 lines) — max's own layers. Its §1 diagram shows + `MaxClient` as the only path; `src/messenger.ts` and `src/adapter/max-adapter.ts` now plug max into + cli-messaging. §17 still describes max's own MCP server. +- `tg-cli/docs/dev/ARCHITECTURE.md` (52 lines) — current and short. +- The site has one architecture page, `content/docs/search-architecture{,.ru,.es}.mdx`, with a + light-only English SVG (`public/search-architecture.svg`). + +**Packages, verified in each `package.json`:** + +- `@leemour/cli-core` — output modes, renderer, error model and exit codes, keyring (optional + `@napi-rs/keyring`), config, clocks; plus `./http`, `./codegen`, `./update`, `./release`, + `./skill`, `./completion`. Also used by `braze-cli` (public). +- `@leemour/cli-messaging` — domain model, store, send guard, services, command skeleton, MCP + server, speech, background. Hard dependencies on `@leemour/cli-messaging-sqlite` and + `@leemour/cli-messaging-onnx` (both 1.0.0). +- `@leemour/tg-cli` — adds `@mtcute/node`; its own code is the Telegram adapter, session, setup, + update. +- `@leemour/max-cli` — adds `ws`, `@msgpack/msgpack`, `lossless-json`; owns the MAX protocol, + session and the official Bot API slice (`src/bot/`). + +**Footer and security links:** + +- The footer HTML comes from `lib/landing/{en,ru,es}.json`, generated by + `scripts/export-landing.mjs` from `design/landing/g-home*.html`. The issue link is injected by + `scripts/export-landing.mjs:196-197`; the security link is `/{lang}/docs/tg/security` in the + prototypes. +- `components/landing/landing.tsx:881,884` has the same two links; the page renders + `components/landing.tsx` (`app/[lang]/(home)/page.tsx:1`). I will check whether the other file is + still imported anywhere before touching it. +- `app/[lang]/(home)/about/page.tsx:71` links Security to `/docs/tg/security`. +- `site.config.json` `contacts.telegram` is `https://t.me/wirecatdev`. Its public page shows + "3 members", which is how Telegram shows a group, not a channel — so I infer it is the support + chat. +- No repository has a `SECURITY.md` or a private way to report a vulnerability. +- Tool pages link to the site only by absolute URL (`max-cli/README.md:13`). `scripts/sync.ts:50` + passes absolute and root links through unchanged, and `scripts/localize.ts:117` requires every + translation to keep the same link destinations. + +## Decisions + +- **D1 · Both guides are shared pages in cli-docs**, like `search-architecture`: one fact, one home. + `content/docs/architecture{,.ru,.es}.mdx` and `content/docs/security{,.ru,.es}.md`. Sidebar: + `architecture` next to `search-architecture`; `security` after `bot-api`. +- **D2 · Diagrams are a React component with labels per language**, not an English image: the + existing SVG shows English text on the Russian page and stays light in dark mode. One + `components/architecture-diagrams.tsx` with inline SVG using the theme's colour variables. Each + diagram is followed by prose that says the same thing, since the Markdown copy for agents + (`/llms.mdx/...`) drops JSX. +- **D3 · The architecture page links code at a pinned commit**, as the search page does, and dates + what it read. It states the limits next to the design: the MAX protocol is unofficial and reverse + engineered; one socket per device for MAX, so writes go through `max serve`; vectors are scanned + in JavaScript with no vector index; store writes block the event loop and other processes wait up + to 5 s for the lock. +- **D4 · The footer reads both links from configuration.** "Report a problem" → + `contacts.telegram`; "Security" → `/{lang}/docs/security`. Changed in the export script and the + prototypes, then re-exported, and checked that the JSON diff touches only those links. +- **D5 · The shared security page holds what cli-core and cli-messaging own**, the same for both + tools: what stays on the computer, the keyring, the shared store and run records (never message + text), the send guard and permissions, MCP `--allow-send` / `--confirm-send`, other people's text + as untrusted input for agents, what goes over the network, how to report a problem. Anything + only one tool has stays on its page. +- **D6 · Tool pages get a link first, trimming second.** A lead line pointing to the shared page, + in a PR to each tool. It appears on the site with each tool's next release; each change needs + its translations re-reviewed (max: en, es; tg: ru, es) and fingerprints updated in + `translations/sources.json`. +- **D7 · Links from a tool page to the site are rewritten per language at sync.** The tool page + writes `https://wirecat.dev/ru/docs/security`; `scripts/sync.ts` turns any + `https://wirecat.dev//docs/` into `//docs/` after translation checks, + so the English copy of a Russian page does not send the reader to Russian. Small and tested in + `scripts/sync.test.ts`. On GitHub the absolute URL still works. + +## Architecture page outline + +1. **What it is in one picture** — diagram A: the packages and who depends on whom (tg-cli, + max-cli → cli-messaging → cli-core; cli-messaging-sqlite, -onnx; mtcute, ws). One line per + package on what it owns. +2. **One command, start to finish** — diagram B: argv → `run()` → settings → guard → service → + adapter → messenger, and the store/run record beside it; the process exits. +3. **Layers** — domain, adapters, ports, services, interface (CLI and MCP). Each calls only the + ones below; Biome import rules enforce it. Diagram C. +4. **Adapters** — the port: required core, optional groups through `capability()`, refusal over + silent drop, ids as strings, `providerMetadata`, `sendId` and `outcome_unknown`, server vs + pushed history (MAX). How tg and max each fill it. Contract cases. +5. **The local store** — one SQLite file for every messenger and account, keyed by provider and + account; Node and Bun drivers; the bundled SQLite where the system one is too old; forward-only + migrations and `min_compatible`; one method, one transaction. Link to the search guide for the + indexes. +6. **Patterns that hold it together** — services shared by commands and MCP tools; decorators that + save and time adapter calls; per-messenger overrides of a use case; stdout carries data only; + closed error codes; one-shot processes close everything; the send guard in one place. +7. **The MAX specifics** — operations declared once in `src/spec/`, generated wrappers, binary + frames, the Bot API slice generated from OpenAPI with cli-core's codegen. +8. **Testing** — sandboxed tests, the fake adapter, contract cases, generated docs checked in CI, + parity checks between tg and max. +9. **Limits and trade-offs** — D3's list. +10. **Contributing: where to start** — links to `ADAPTERS.md`, each repository's + `ARCHITECTURE.md`, `CONVENTIONS.md`. +11. **Sources** — pinned links. + +## Work items (in order) + +1. Footer and About links (D4) — cli-docs PR 1. Smallest, independent. +2. Shared security page in three languages, sidebar, footer pointing to it — cli-docs PR 1 too, + since the footer needs the page to exist. +3. Architecture page, diagram component, three languages, `search-intents.json` entries if the + search needs them — cli-docs PR 2. +4. Sync rewrite of site links (D7) — cli-docs PR 2 or 3. +5. Lead link on `max-cli/docs/security.md` and `tg-cli/docs/security.md`; correct the stale + sections in `cli-messaging/docs/dev/ARCHITECTURE.md` ("Who consumes it") and + `max-cli/docs/dev/ARCHITECTURE.md` (§1, §17) in place — one PR per repository, each on `main`. +6. After the next tg and max releases: re-review the four security translations and update the + fingerprints. + +## Checks + +`pnpm lint && pnpm typecheck && pnpm test`, `pnpm sync && pnpm exec next build && pnpm check:links`; +open `/en|ru|es/docs/architecture` and `/security` in light and dark, phone width; the footer links +on the landing and on a docs page. In each tool repository its own `pnpm lint && pnpm typecheck && +pnpm test`. + +## Open questions + +- **NEED-554 · Support link:** is `https://t.me/wirecatdev` the support chat for "Report a problem"? + (Inferred from "3 members".) +- **NEED-555 · Vulnerability reports:** where does someone report a security problem privately — + `hello@wirecat.dev`, GitHub private vulnerability reporting on each repository, or both? +- **NEED-556 · Trimming tool security pages:** after the link lands, should the generic sections that + the shared page now covers be cut from the tool pages, or stay duplicated? From 0ac98c47a7c8883dfcac1b8ab20df9c6aa1bf53a Mon Sep 17 00:00:00 2001 From: leemour Date: Sun, 4 Oct 2026 13:26:57 +0200 Subject: [PATCH 2/5] fix(footer): report problems in the support chat, security on the shared page "Report a problem" pointed at tg-cli's GitHub issues and "Security" at tg's own page. Both now lead to the support chat and the shared security page, in the landing prototypes, the export and the About page. Co-Authored-By: Claude Opus 5.5 (1M context) --- app/[lang]/(home)/about/page.tsx | 2 +- design/landing/g-home.es.html | 4 ++-- design/landing/g-home.html | 4 ++-- design/landing/g-home.ru.html | 4 ++-- lib/landing/en.json | 2 +- lib/landing/es.json | 2 +- lib/landing/ru.json | 2 +- scripts/export-landing.mjs | 4 ++-- 8 files changed, 12 insertions(+), 12 deletions(-) diff --git a/app/[lang]/(home)/about/page.tsx b/app/[lang]/(home)/about/page.tsx index 57b6445..b769785 100644 --- a/app/[lang]/(home)/about/page.tsx +++ b/app/[lang]/(home)/about/page.tsx @@ -82,7 +82,7 @@ export default async function AboutPage({ params }: Props) { max · {words.source}