Commit Graph

139 Commits

Author SHA1 Message Date
mix 5b63da0e49 ci: trigger release workflow on published GitHub Release
test / test (push) Has been cancelled
Bare git tag pushes no longer start the image build; publishing a GitHub
Release does. workflow_dispatch still requires an explicit X.Y.Z version.
Docs explain draft vs published releases and that deleting a tag on GitHub
converts a published release back to draft.

Co-Authored-By: Cursor <cursoragent@cursor.com>
2026-08-14 19:43:06 +03:00
mix 1bd71c10d0 docs: align operator docs with routes, sessions, and restore
test / test (push) Has been cancelled
Fix architecture route RBAC, restore Resync, and session/password wording;
correct guide restore/session/PTR claims and README port-587 text; point
the CSRF ADR at authz.go for global route gating.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-14 19:36:24 +03:00
mix 4fc5cff266 docs(guide): add worked restore commands to Full backup and restore
test / test (push) Has been cancelled
The section explained what a restore means conceptually but gave no
runnable commands. Add a step-by-step in-place restore, a
move-to-a-new-host variant, and the encrypted-backup decrypt-first
sequence, plus the actual version-mismatch error text so operators
know what to expect.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-14 19:18:54 +03:00
mix ac8c2af500 docs(guide,architecture): move internal env vars out of the operator guide
test / test (push) Has been cancelled
Internal (non-operator) env vars were listed in guide.md's Environment
variables section even though the guide's own text says operators
aren't meant to touch them. They now live in architecture.md §
Configuration, the as-built/internals doc; guide.md keeps a one-line
pointer.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-14 19:13:33 +03:00
mix 9e3f0d0fad docs(guide): reorder Installation and add a Full deployment walkthrough
test / test (push) Has been cancelled
Installation now reads Ports, Local trial, Initial setup, Full
deployment (with Fixed image tag nested under it), Environment
variables, Reverse proxy. The step-by-step production deploy and the
per-proxy TLS commands move from README's "Reference deploy" into the
operator guide; README keeps a short pointer instead of duplicating
the walkthrough.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-14 15:49:58 +03:00
mix 403c76d17d docs(guide): restructure into Installation / Instance admin / Domain admin
test / test (push) Has been cancelled
Splits mixed DNS-setup, Operations, Rate-limiting, and Backup sections
along the instance/domain boundary and fixes README anchors that
pointed at the old #dns-setup heading.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-14 15:45:38 +03:00
mix d9ab7bfa45 docs: retire the completed full-tree review plan
test / test (push) Has been cancelled
Every phase (P0-P7) is closed, so the plan file goes per its own exit criteria; history lives in git and the CHANGELOG. The roadmap's recommended order returns to queue-retries and then inbound-relay, and the order notes in both plans stop pointing at the deleted file, as does the 1.2.5 changelog entry (same treatment as logrotate-mode.md).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-14 15:23:52 +03:00
mix 18bfd148ec docs: close P7 — security review of the P0–P1 diff, no findings
The Fable review of the send-log authorization, tryAdmit, session create and app-delete ordering against security.md found no further issues: every send-log query path states its scope and an empty scope matches nothing, rejected rows cannot consume rate-limit budget, the milter's nil-registry fail-open is test-only, and each failure residue of the reordered delete fails safe. Outcome recorded in security.md's header and the plan; nothing added to the accepted risks.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-14 15:02:07 +03:00
mix e70ba9046e fix(panel): resync mail-path maps once after restore
When CheckRestore accepts a backup manifest, the panel re-derives OpenDKIM tables and the Postfix sender map from SQLite on that first boot and reloads both daemons, so archive/database drift is healed before mail flows.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-14 14:58:08 +03:00
mix 02afa0fa80 fix(panel): code-review P6 optional cleanup
test / test (push) Has been cancelled
Close the remaining low-risk items from the full-tree review: rename the settings handler, query assigned domains in SQL, bound the login limiter map, collapse panel.js show/hide helpers, and soften DMARC copy that promised a future in-panel receiver.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-14 14:48:43 +03:00
mix 97a0c7e508 licence,ci: ship OFL with Plex fonts and guard release dispatch (P5)
test / test (push) Has been cancelled
IBM Plex WOFF2 files were shipped without the SIL OFL 1.1 text, NOTICE
told modifiers to edit layout.html for a Source URL that lives in
legal.go, and workflow_dispatch took GITHUB_REF_NAME as the version so a
run from main would publish ghcr.io/...:main.

Closes P5 of docs/plans/code-review.md. CHANGELOG updated.

Co-Authored-By: Cursor Grok 4.6 <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-14 09:47:33 +03:00
mix efdc2d63fb docs: agree queue-retries (Postfix retry policy in the panel)
test / test (push) Has been cancelled
Roadmap item and plan: show first retry delay, backoff cap and queue
lifetime on Mail queue and the delivery page, reading postconf -h once
at panel start so a manual override is visible. Explanation only; not
implemented yet. CHANGELOG updated.

Co-Authored-By: Cursor Grok 4.6 <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-13 23:51:13 +03:00
mix 8dfb483244 test: boot a panel on a data directory restored from its own backup (P4)
test / test (push) Has been cancelled
Restore is not a code path in the panel — the operator extracts the archive
onto /data and starts the image — so it had no test. cmd/panel/restore_test.go
now performs that path in process: download a backup from a running panel
through POST /backup (plain and encrypted), unpack it the way tar -xzf does,
and boot a second panel on the result through run()'s own startup order
(CheckRestore, store.Open, newPanel, Start).

Covered: the restored panel shows the domain and journal the archive carried
and finds the DKIM key, sasldb2 and Postfix sender map where its configuration
says they are; the setup link is not reopened by a restore; a session that
predates the backup still works, as the guide documents; an encrypted download
restores identically; a data directory from another version is refused with
both versions named and the manifest kept for the retry.

serveHTTP is split so the composition it performs (newPanel) can be started
without binding a port. No behaviour change.

Closes the optional P4 item in docs/plans/code-review.md, and with it the
"HandleBackup POST untested" gap from the review's test section. CHANGELOG
updated.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-13 23:46:01 +03:00
mix e6af1a7866 test: cover the auth, sign-in and RBAC surfaces P0 shipped through (P4)
test / test (push) Has been cancelled
- internal/web/auth/ratelimit_test.go: the login/setup limiter's ceiling,
  per-address scope, window reset and the sweep that keeps finished
  buckets out of memory.
- internal/web/auth/handlers_test.go: sign-in (session issued, refusals
  that do not reveal which usernames exist, a lockout a correct password
  cannot bypass, the setup hint before the first administrator) and the
  one-time setup link (creates the first global administrator and then
  closes, rejects a wrong or expired token, refuses credentials the panel
  would not accept later, rate-limited).
- internal/web/handlers/authz_test.go: every global-only route answers a
  domain administrator — and a request with no principal — with 404, with
  a positive control so the table cannot pass on a handler that always
  404s. This is the check that would have caught the send-log leak.
- test/e2e: CoreDNS pinned to 1.14.6 instead of latest; the level-1
  failure message quoted RATE_LIMIT_MESSAGES_PER_IP=5 while the stand
  sets 50.

docs/plans/code-review.md P4 checked off except the optional backup-boot
test; CHANGELOG updated. No production code changed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-13 23:35:46 +03:00
mix aab35f0679 fix(panel): P3 optional items — urlquery, aria-live, confirm-without-JS note
- Deliveries fragment/pagination links urlquery-encode the domain/app
  filters instead of splicing them into the query string raw.
- The four polled regions (deliveries rows, status, mail queue, system
  log) carry aria-live="polite" so a screen reader announces refreshes.
- security.md accepted risks note that data-confirm prompts are
  JavaScript-only and why that is acceptable.

docs/plans/code-review.md P3 fully checked off; CHANGELOG updated.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-13 22:54:31 +03:00
mix 0570608738 fix(panel): GUI defects from the 1.2.x layout pass (P3)
- .flash.error now renders on the danger surface instead of the success
  one; RateLimitErr previously showed as green with red text.
- User delete goes through a confirmation page (GET/POST
  /users/{uid}/delete), matching the domain-delete pattern, instead of a
  plain submit button next to Save with no confirmation.
- Extracted the repeated DNS Host/Type/Value markup on a domain's page and
  the duplicated Settings credentials form into shared partials. No
  behaviour change.

docs/plans/code-review.md P3 checked off; CHANGELOG updated.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-13 21:50:42 +03:00
mix 1cf8bfcbe2 docs: rewrite security/operator docs for the multi-user panel (P2)
test / test (push) Has been cancelled
The CSRF ADR, guide.md, architecture.md route table, the internal/backup
package comment, roadmap/dmarc-reports admin.dmarc_report_email references,
the e2e coverage summary, and the setupManager/store package comments still
described the pre-1.2.0 single-administrator panel or stale implementation
details. Closes P2 of docs/plans/code-review.md; no behaviour change.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-13 16:15:14 +03:00
mix 4761991dd5 panel,mail: fail closed on the rate-limit race, session create and app delete
test / test (push) Has been cancelled
The level-2 limiter counted stored plus in-flight messages and reserved its own slot in two critical sections, so SMTP sessions that overlapped could each take the last free slot; tryAdmit now does both under one lock. A session that cannot be written no longer yields a cookie the browser would carry while every request bounced to /login. Deleting an application clears its SASL account before its registry row, matching domain delete, so a saslpasswd2 failure leaves a retryable application rather than an account that still authenticates.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-13 14:50:04 +03:00
mix fae0068c4a panel: scope the send log to a domain admin's own domains
test / test (push) Has been cancelled
The Deliveries list narrowed the journal only when exactly one domain was assigned, so an administrator with none or with two or more read every domain's rows. The domain scope is now an IN constraint the store query carries, a filter that states no scope matches nothing, and the domain/app query parameters are validated against the principal before the query runs.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-13 12:20:51 +03:00
mix b829625066 docs: record full-tree review and 2.x schema squash
test / test (push) Has been cancelled
Capture the 2026-08-13 review as the active plan, queue it ahead of inbound-relay, and defer SQLite migration squash to 2.x with a user_version gate.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-13 01:36:08 +03:00
mix 71048922b9 release: 1.2.5
test / test (push) Has been cancelled
Close Unreleased for the rate-limit form polish; pin compose and docs to 1.2.5.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-13 01:04:19 +03:00
mix 6671bd3393 release: 1.2.4
test / test (push) Has been cancelled
release / prepare (push) Has been cancelled
release / build (amd64, ubuntu-latest) (push) Has been cancelled
release / build (arm64, ubuntu-24.04-arm) (push) Has been cancelled
release / merge (push) Has been cancelled
Close Unreleased for the level-2 rate-limit semantics change and DNS Type
field height fix; pin compose and docs to 1.2.4.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-12 23:21:28 +03:00
mix 00e36df553 rate limit: domain ceiling for all IPs, trusted app override
Invert level-2 semantics so domain limits apply to every client IP and
application limits with trusted IPs raise the ceiling above the domain
(still capped by level 1). Panel shows L1, validates maxima, and documents
the model on Settings.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-12 23:19:51 +03:00
mix 601e183e0c release: 1.2.3
Close CHANGELOG [Unreleased] as 1.2.3; bump the compose pin and image references. Includes domain detail layout polish and Domains add-row.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-12 22:52:19 +03:00
mix 1d30605533 panel: align page URLs, titles, and headings
test / test (push) Has been cancelled
Settings moves to /settings with a 308 redirect from /account; domains, Status, Users, and user forms get matching browser titles and h1 text; backup page title reflects domain import.

Co-Authored-By: Composer <noreply@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-12 15:24:14 +03:00
mix b87baa6dd6 fix: pin logrotate config mode in image and fail loud on bad permissions
test / test (push) Has been cancelled
COPY --chmod makes /etc/logrotate.d/mail 0644 regardless of build context
file modes (Windows tar sync). logrotate-loop preflight exits non-zero when
logrotate would ignore the config. E2e covers mode, forced rotation, and a
group-writable context build.

Co-Authored-By: Composer 2.5 <noreply@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-12 00:51:37 +03:00
mix 9420e30d6f release: 1.2.2
test / test (push) Has been cancelled
Close CHANGELOG [Unreleased] as 1.2.2; bump the compose pin and image references.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-12 00:34:09 +03:00
mix 93cf1de3b7 panel: denser Status layout with true two-column cards
test / test (push) Has been cancelled
Pair Machine|Processes, queue|cert, and sockets|hostname; fix .split
auto-margins so cards fill half the row; trim Status prose and machine
details; drop the page section index; note panel-docs on the roadmap.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-12 00:29:34 +03:00
mix 4015ecd70d release: 1.2.1
test / test (push) Has been cancelled
Close CHANGELOG [Unreleased] as 1.2.1; bump the compose pin and image references.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-11 23:03:54 +03:00
mix bc005dea85 release: 1.2.0
test / test (push) Has been cancelled
Close CHANGELOG [Unreleased] as 1.2.0; correct missing entries; bump the
compose pin and image references.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-11 17:39:11 +03:00
mix 4b2f3880ef panel: align heading with narrow cards on signed-in pages
Settings and the user form centred the title on the 48rem measure while
.card.narrow centred on 24rem, so their left edges drifted by 12rem. Cap every
direct child of main when a narrow card is present, without shrinking the
column, so navigation stays put and login/setup stay unchanged.

Co-Authored-By: Cursor <cursoragent@cursor.com>
2026-08-11 17:34:04 +03:00
mix c443149623 docs: plan the narrow pages' heading alignment
test / test (push) Has been cancelled
Settings and the user form leave their heading at the left of the reading
measure while the card floats 12rem to the right of it. main > * caps every
child at 48rem and centres it; .card.narrow overrides the max-width down to
24rem but not the auto margins it never mentions, so the two centre on
different measures and half the difference is the offset.

Records what the question was actually about: not what is wrong with Settings
but what it shares with exactly one other page. Four templates use the narrow
card and eleven use a full-width one, which sorts every page into three groups
— full-width card, narrow card without navigation, narrow card with it — and
only the last has the problem. Settings and the user form are the only pages
that are both signed-in and built from a single narrow card; every other page
has one of those properties, never both.

Also records why the obvious fix is unavailable, so it is not tried a fourth
time: the shell centres the navigation and the page as a pair, so anything that
changes the column width is visible from the navigation (296px, measured). The
fix has to work inside the column.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-11 10:19:11 +03:00
mix 5eaf665c01 docs: remove completed plans and trim the open-work tracker
test / test (push) Has been cancelled
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-11 01:34:04 +03:00
mix 8ed20b0c98 docs: plan the logrotate mode defect
test / test (push) Has been cancelled
An image whose /etc/logrotate.d/mail is group-writable makes logrotate ignore
the file, so mail.log never rotates and grows until the volume does. The file
is 0644 in git and is widened on the way into the build context: COPY takes the
mode it finds, and an archive made from a checkout without POSIX permissions
carries the umask-widened one. Measured at 0644, 0664 and 0666 across three
images built on one host from the same commit range.

Written up rather than patched because three things are wrong and fixing the
visible one hides the rest: every COPY in the image trusts the build context,
logrotate exits 0 while ignoring the file so the rotate loop reports success,
and nothing anywhere notices that a rotation did not happen. Whether the
release workflow's own images are affected is stated as unverified — the
published image could not be pulled to check.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 00:56:49 +03:00
mix bd7a3b123d docs: close the CSP and font-ETag check against the test server
Deployed at 1.1.0-post.669f928: the policy is untouched and still admits the
fonts, each comes back as font/woff2 with a content ETag that answers a
matching If-None-Match with 304, and the signed-out page renders in Plex over
the network. The remaining open items all need a signed-in session with real
mail behind it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 00:49:45 +03:00
mix 669f928b4d docs: record what the visual-style pass left open
test / test (push) Has been cancelled
Five things, each written down so the next pass does not rediscover them: the
send log's bare-text status and the mapping question that keeps it from being a
pure repaint, the 375px horizontal overflow that predates this work, the three
views only ever seen empty because they need a running Postfix, the CSP and
ETag checks that a file:// render cannot make, and font-display: swap, which
never had a cold load to show itself in.

Also records how the pages were reached at all — the stubs and seeded rows
without which half the panel does not exist on a development machine.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 00:40:34 +03:00
mix c9d726dd64 docs: agree the visual-style plan
test / test (push) Has been cancelled
The mark was approved on its own sheet and the panel was left on the default
blue-on-cool-grey it shipped with, so the two read as different designs. Write
down what the panel takes from the proof — brick as the accent, warm paper,
IBM Plex self-hosted — and what it deliberately does not: the proof's mock puts
navigation in a dark top bar, which has nowhere to keep the per-page section
index the left column carries.

Records the decisions that cost something to reverse: three font files (76 KB)
served from the panel's own origin so the CSP stays default-src 'self', brick
split into a fill and a text value because #7A3B2E is unreadable as a link on
the dark scheme, and the test that outranks all of it — the accent must not be
mistakable for a status badge.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 00:06:12 +03:00
mix c9076655b9 docs: expand domain-admin plan with schema, routes, and UI spec
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-10 23:36:09 +03:00
mix e34d81498e release: 1.1.0
Close CHANGELOG [Unreleased] as 1.1.0; remove erroneous DMARC entries
retroactively copied into older sections; bump the compose pin and image
references.

Co-Authored-By: Cursor <cursoragent@cursor.com>
2026-08-10 23:30:46 +03:00
mix 155b721438 Split internal/web into subpackages before domain-admin growth.
test / test (push) Has been cancelled
Lay out view, auth, validate, and handlers under internal/web while keeping
the cmd/panel API unchanged; update roadmap and changelog for web-split closure.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-10 23:19:09 +03:00
mix efaf016c5f Fix DMARC guidance for send-only relays with optional rua= settings.
test / test (push) Has been cancelled
The panel now suggests policy-only DMARC by default, lets operators configure a default and per-domain report address, and DNS-checks hub _report._dmarc records. Future in-panel report ingestion is tracked as dmarc-reports in the roadmap.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-10 22:47:34 +03:00
mix 2bdc0ea9a8 docs: add visual-style candidate to roadmap
test / test (push) Has been cancelled
Track optional panel visual refresh in the 1.x+ tracker; changelog under Unreleased.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-10 22:02:24 +03:00
mix 6c8bf0d3b3 legal: close AGPL packaging gaps
test / test (push) Has been cancelled
Name the copyright holder, ship NOTICE with the image, serve the licence
from the panel footer on every page, and record the vendored htmx licence.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-10 21:56:51 +03:00
mix c713f51f24 release: retag 1.1.0 as 1.0.1
test / test (push) Has been cancelled
The cut is docs and packaging plus one bugfix — PATCH, not MINOR. v1.1.0 was never tagged.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-10 21:42:40 +03:00
mix 0ed36e9624 release: 1.1.0
test / test (push) Has been cancelled
Close the [Unreleased] section as 1.1.0 and move the deploy pin, the README
trial command, and the guide's stated pin to that tag.

Corrections to the section while cutting it:

- The GHCR "unknown blob" retry was filed under Unreleased, but the commit
  carrying it is what v1.0.0 points at. Moved into the 1.0.0 section.
- docs/plans/ and the roadmap's restructure into a 1.x+ tracker were missing
  entirely; the plans were described only as "translated", which reads as if
  they predated this release. Filed under Added.
- docs/product.md's reframing of the future line -- agreed 1.x+ extensions,
  inbound relay targeting a MINOR by default, approval needed only for
  candidates -- was unrecorded.
- The Account/Settings rename also touched the operator guide.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-09 23:39:53 +03:00
mix 01c754f857 docs: record the decision to disclose AI authorship
test / test (push) Has been cancelled
The question kept resurfacing while preparing the repository for publication,
so it is written down as settled rather than re-argued: SelfPost is written by
AI agents under a maintainer's direction and the project says so.

What that commits to is listed explicitly — the Co-Authored-By trailers, the
model routing table, the .cursor rules file, and the agent-facing process notes
in the roadmap all stay, and none of them is an oversight to be tidied away.
The reasoning is that with the trailers already in ~140 commits, removing the
surrounding material would not conceal authorship, only signal an attempt at
it.

The revisit condition is deliberately narrow: a conflict with the licence or a
downstream obligation, not a shift in convention.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-09 23:14:27 +03:00
mix 691d3c255f docs: point the README at SECURITY.md and disambiguate the two security docs
test / test (push) Has been cancelled
A reader looking for where to report a flaw had no path from the README: the
only security row led to docs/security.md, which is the design rationale, not
a reporting channel. That row is now "Security design", and a line under the
table sends vulnerability reports to SECURITY.md instead of the issue tracker.

development.md gains SECURITY.md in its user-facing deliverables table and
drops "internal" from the roadmap row, which stopped being true when the
roadmap was reframed for outside readers.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-09 22:58:56 +03:00
mix 295d1afb7d docs: translate the three plans
test / test (push) Has been cancelled
The roadmap links straight into these files, so a reader following an item
landed in Russian one click after an English page. Translated in full; goals,
boundaries, done-when criteria and risks are unchanged in substance.

The model assigned to inbound-relay is dropped, as it was from the roadmap
item: model routing lives in development.md.

Figures and code references were checked against the tree while translating
rather than copied forward — internal/web is still 50 files, 25 .go, ~4300
lines, and requireAuth(authed) and sendLogData are still where domain-admin.md
says they are.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-09 22:50:38 +03:00
mix 06c2014384 docs: translate the roadmap and frame it for an outside reader
test / test (push) Has been cancelled
roadmap.md is linked from the README table, so it is a page strangers land on.
Translated in full, with a note up front that none of it is a commitment:
there are no dates, the order is a recommendation, and an item can be dropped
once its plan is written. The note also points at product.md for the opposite
question — what the project deliberately will not do — so absence from the
roadmap is not read as a silent plan.

The model assigned to inbound-relay is dropped from the item; model routing
belongs in development.md, not in a statement of direction.

The README row described the file as internal and Russian. It is now neither.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-09 22:46:58 +03:00
mix 236cb07769 docs: translate security.md and the last Russian source comments
security.md is linked from the README documentation table and now from
SECURITY.md, so a reader following either link landed in a Russian document
while everything around it was English. Translated in full; the requirements,
the accepted risks, and the CSRF ADR are unchanged in substance.

The reviewing model is no longer named in the text — that the pre-release
review ran, and when, is what a reader needs; who ran it is process detail
kept in development.md.

extract-cert.sh keeps its spec 10.3 quotation, translated. In sasl.go the
quotation from the closed plan is dropped rather than translated: rendered in
English it restated the sentence it hung off.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-09 22:39:53 +03:00