R6(a): de-stage code, docs, READMEs; split stage6_test

Mechanical, behaviour-preserving removal of Stage N / TODO-N / phase (RN)
references from comments, doc-comments, service READMEs, the current-state docs
(ARCHITECTURE, FUNCTIONAL+_ru, TESTING, UI_DESIGN), config-file comments, and the
.fbs/.proto schema comments. PLAN.md / PRERELEASE.md / CLAUDE.md keep the stage
history.

- Rename the only stage-named identifiers: registerStage8 -> registerSocialOps,
  registerStage11 -> registerLinkOps (gateway transcode).
- Split stage6_test.go: TestEmailLoginFlow -> email_test.go,
  TestGuestAutoMatchLeavesNoStats (+ provisionGuest) -> account_test.go.
- Regenerated proto bindings (push.pb.go, telegram_grpc.pb.go) from the de-staged
  .proto comments; FB Go/TS bindings unchanged (flatc strips schema comments).

go build/vet/gofmt clean across modules; integration typecheck and pnpm check green.
This commit is contained in:
Ilia Denisov
2026-06-10 16:56:03 +02:00
parent a372343797
commit 8881214213
156 changed files with 749 additions and 778 deletions
+1 -1
View File
@@ -7,7 +7,7 @@ import (
// TestPeerIP covers the client-IP extraction the chat-moderation IP and the per-IP rate
// limiter both rely on: the first X-Forwarded-For hop (the real client, once Caddy is
// configured to trust its upstream), falling back to the connection peer (Stage 17).
// configured to trust its upstream), falling back to the connection peer.
func TestPeerIP(t *testing.T) {
tests := []struct {
name string
+13 -13
View File
@@ -35,7 +35,7 @@ import (
const heartbeatKind = "heartbeat"
// Limiter classes, the `class` attribute of gateway_rate_limited_total and the
// class field of the periodic rejection report (R3).
// class field of the periodic rejection report.
const (
classUser = "user"
classPublic = "public"
@@ -43,13 +43,13 @@ const (
classAdmin = "admin"
)
// Explicit h2c server sizing (R3, after the R2 stress run questioned the
// implicit defaults).
// Explicit h2c server sizing, made explicit rather than relying on the
// implicit defaults.
const (
// h2cMaxConcurrentStreams bounds the open streams per client connection — the
// x/net default made explicit. A real client holds one Subscribe stream plus a
// few unary calls; only a synthetic load multiplexing many players over one
// transport approaches it. R7 revisits the sizing.
// transport approaches it.
h2cMaxConcurrentStreams = 250
// h2cIdleTimeout closes a connection with no open streams. A live Subscribe
// stream keeps its connection active, so long-lived clients are unaffected;
@@ -151,7 +151,7 @@ func (s *Server) HTTPHandler() http.Handler {
// working over h2c (docs/ARCHITECTURE.md §12). In the deployed contour the
// front caddy owns the /_gm Basic-Auth and Grafana routing; this mount serves
// a non-caddy (local) setup. The per-IP admin limiter class guards it —
// notably a Basic-Auth brute force (R3).
// notably a Basic-Auth brute force.
mux.Handle("/_gm/", s.limitAdmin(s.adminProxy))
} else {
// With the console disabled here, keep /_gm a 404 so the SPA catch-all below
@@ -162,14 +162,14 @@ func (s *Server) HTTPHandler() http.Handler {
// Mini App) — the single-origin model (docs/ARCHITECTURE.md §13). Both sit below
// the h2c wrap so the Connect edge (a more specific prefix) keeps priority, and
// each mount falls back to the app shell (index.html) for the hash router. The
// public landing moved to its own static container behind the contour caddy
// (R3), so the catch-all redirects a stray root hit to the app shell — which
// public landing lives in its own static container behind the contour caddy,
// so the catch-all redirects a stray root hit to the app shell — which
// keeps a local no-caddy run usable.
mux.Handle("/telegram/", webui.Handler("/telegram/", "index.html"))
mux.Handle("/app/", webui.Handler("/app/", "index.html"))
mux.Handle("/", http.RedirectHandler("/app/", http.StatusPermanentRedirect))
// Every request body on the public listener is capped (the admin proxy POSTs
// included); the h2c server carries explicit stream/idle sizing (R3).
// included); the h2c server carries explicit stream/idle sizing.
return h2c.NewHandler(maxBodyHandler(s.maxBodyBytes, mux), &http2.Server{
MaxConcurrentStreams: h2cMaxConcurrentStreams,
IdleTimeout: h2cIdleTimeout,
@@ -264,7 +264,7 @@ func (s *Server) Subscribe(ctx context.Context, req *connect.Request[edgev1.Subs
// Send an immediate heartbeat so the stream's first byte flushes through the proxy chain
// right away and resets edge/client idle timers, instead of the connection sitting silent
// until the first tick — which otherwise raced a ~15 s idle timeout and forced a reconnect
// every interval (Stage 17).
// every interval.
if err := stream.Send(&edgev1.Event{Kind: heartbeatKind}); err != nil {
return err
}
@@ -294,7 +294,7 @@ func (s *Server) Subscribe(ctx context.Context, req *connect.Request[edgev1.Subs
// noteRateLimited accounts one limiter rejection: the aggregate counter, the
// per-rejection Debug line and the periodic-report tracker. The operational
// signal is the reporter's Warn summary; per-rejection logging stays at Debug so
// a rejection flood cannot flood the log (R3).
// a rejection flood cannot flood the log.
func (s *Server) noteRateLimited(ctx context.Context, class, key, msgType string) {
s.metrics.recordRateLimited(ctx, class)
s.tracker.Add(class, key)
@@ -315,7 +315,7 @@ func (s *Server) rejectRateLimited(ctx context.Context, class, key, msgType stri
// of its Basic-Auth check (a credential brute force is exactly what it bounds).
// It covers the gateway-fronted /_gm mount; in the deployed contour /_gm reaches
// the backend through caddy, whose Basic-Auth has no limiter (stock caddy) — see
// docs/ARCHITECTURE.md §12 (R3).
// docs/ARCHITECTURE.md §12.
func (s *Server) limitAdmin(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ip := peerIP(r.RemoteAddr, r.Header)
@@ -340,8 +340,8 @@ func (s *Server) resolve(ctx context.Context, h http.Header) (string, error) {
// An unknown or expired token (a backend 4xx) is the client's problem and
// stays silent; anything else — a resolve timeout, a refused connection, a
// backend 5xx — is an infra failure misread as "unauthenticated" by the
// client, so surface the cause (the transient resolves seen under load in
// the R2 stress run). The token itself is never logged.
// client, so surface the cause (the transient resolves seen under load).
// The token itself is never logged.
var apiErr *backendclient.APIError
if !errors.As(err, &apiErr) || apiErr.Status >= http.StatusInternalServerError {
s.log.Warn("session resolve failed", zap.Error(err))
+4 -4
View File
@@ -85,7 +85,7 @@ func TestExecuteAuthedRequiresSession(t *testing.T) {
// TestExecuteRateLimitedTracked verifies a limiter rejection returns
// ResourceExhausted and lands in the rejection tracker under the public class,
// keyed by the client IP (R3).
// keyed by the client IP.
func TestExecuteRateLimitedTracked(t *testing.T) {
backendSrv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
_, _ = w.Write([]byte(`{"token":"tok","user_id":"u-1","is_guest":true,"display_name":"Guest"}`))
@@ -135,7 +135,7 @@ func TestExecuteRateLimitedTracked(t *testing.T) {
}
// TestAdminMountRateLimited verifies the /_gm mount is guarded by the per-IP
// admin limiter class ahead of the proxy's Basic-Auth (R3).
// admin limiter class ahead of the proxy's Basic-Auth.
func TestAdminMountRateLimited(t *testing.T) {
backendSrv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}))
defer backendSrv.Close()
@@ -181,7 +181,7 @@ func TestAdminMountRateLimited(t *testing.T) {
// TestExecuteOversizedPayloadRejected verifies the request-body cap: an Execute
// message above GATEWAY_MAX_BODY_BYTES is refused at the edge without reaching
// the backend (R3).
// the backend.
func TestExecuteOversizedPayloadRejected(t *testing.T) {
client, cleanup := newEdge(t, func(w http.ResponseWriter, r *http.Request) {
t.Error("backend must not be called for an oversized payload")
@@ -198,7 +198,7 @@ func TestExecuteOversizedPayloadRejected(t *testing.T) {
}
// TestRootRedirectsToApp verifies the gateway no longer serves a landing at "/"
// (it lives in the landing container since R3): a stray root hit is redirected
// (it lives in the landing container): a stray root hit is redirected
// to the app shell.
func TestRootRedirectsToApp(t *testing.T) {
front := httptest.NewServer(connectsrv.NewServer(connectsrv.Deps{}).HTTPHandler())