mirror of
https://github.com/MeshTender/MeshTender.git
synced 2026-09-01 17:38:15 +00:00
Fix spelling
This commit is contained in:
@@ -268,7 +268,7 @@ type janitorSweep struct {
|
||||
|
||||
// runJanitor runs every sweep once on entry — so a restart cleans up immediately
|
||||
// instead of waiting out the first interval — then again every `every` until ctx is
|
||||
// cancelled.
|
||||
// canceled.
|
||||
//
|
||||
// This lives here rather than on the analytics rollup ticker, which also prunes on
|
||||
// the same cadence, because analytics has no business knowing about auth codes or
|
||||
|
||||
@@ -96,7 +96,7 @@ func TestJanitorStopsOnCancel(t *testing.T) {
|
||||
select {
|
||||
case <-done:
|
||||
case <-time.After(2 * time.Second):
|
||||
t.Fatal("runJanitor did not return after ctx was cancelled — shutdown would hang")
|
||||
t.Fatal("runJanitor did not return after ctx was canceled — shutdown would hang")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ func New(st *store.Store, cfg *config.Config) *Recorder {
|
||||
return &Recorder{st: st, cfg: cfg, salt: salt, ch: make(chan store.AnalyticsEvent, bufferSize)}
|
||||
}
|
||||
|
||||
// Run owns the write + rollup loops until ctx is cancelled. Start it in a
|
||||
// Run owns the write + rollup loops until ctx is canceled. Start it in a
|
||||
// goroutine. A nil Recorder's Run is a no-op.
|
||||
func (rec *Recorder) Run(ctx context.Context) {
|
||||
if rec == nil {
|
||||
@@ -75,7 +75,7 @@ func (rec *Recorder) Run(ctx context.Context) {
|
||||
case <-ctx.Done():
|
||||
// Drain anything still queued (e.g. events recorded while in-flight
|
||||
// requests were draining) into the batch, then final-flush on a fresh
|
||||
// context since ctx is already cancelled.
|
||||
// context since ctx is already canceled.
|
||||
for drained := true; drained; {
|
||||
select {
|
||||
case e := <-rec.ch:
|
||||
|
||||
@@ -20,7 +20,7 @@ func analyticsMigrate(dsn string) error {
|
||||
return s.Migrate(ctx)
|
||||
}
|
||||
|
||||
// TestRunFlushesQueuedEventsOnShutdown: when Run's context is cancelled, it drains
|
||||
// TestRunFlushesQueuedEventsOnShutdown: when Run's context is canceled, it drains
|
||||
// events still queued in the channel and persists them in the final flush, rather
|
||||
// than dropping them. This is what lets main.go stop the flusher after the HTTP
|
||||
// drain without losing the events recorded during that window.
|
||||
|
||||
@@ -24,7 +24,7 @@ const (
|
||||
consoleIdleTimeout = 5 * time.Minute
|
||||
// consoleEndTimeout bounds the deferred EndConsoleSession stamp that runs when
|
||||
// a console handler returns (including on shutdown drain). It uses a fresh
|
||||
// background context — the session context is already cancelled by then — so
|
||||
// background context — the session context is already canceled by then — so
|
||||
// the stamp still lands. WSDrainTimeout MUST exceed this (plus unwind slack) or
|
||||
// the drain gives up before the stamp completes and the session is orphaned as
|
||||
// "in progress" forever (see TestDrainWebSockets).
|
||||
@@ -334,7 +334,7 @@ func (s *Handlers) wsConsole(w http.ResponseWriter, r *http.Request) {
|
||||
case errors.Is(err, mesh.ErrNoReply):
|
||||
_ = bridge.Status("warning", "Couldn't reach the repeater to establish a session — commands will still be attempted (flood), but may not work if it doesn't recognize MeshTender.")
|
||||
case err != nil:
|
||||
return // context cancelled
|
||||
return // context canceled
|
||||
default:
|
||||
if userPathSet {
|
||||
reportPathOutcome(bridge, lr)
|
||||
@@ -411,7 +411,7 @@ func (s *Handlers) wsConsole(w http.ResponseWriter, r *http.Request) {
|
||||
case errors.Is(err, mesh.ErrNoReply):
|
||||
_ = bridge.Status("noreply", "No reply received after several tries — the command may still have run.")
|
||||
default:
|
||||
// context cancelled or a build/transmit error
|
||||
// context canceled or a build/transmit error
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -146,7 +146,7 @@
|
||||
<p class="text-secondary small">
|
||||
Violations caused by browser extensions injecting into a visitor's page. Nothing here is a bug in
|
||||
MeshTender and none of it is fixable from our side — it's kept only so an extension can be
|
||||
recognised as the cause rather than mistaken for an app problem. Note that an extension injecting
|
||||
recognized as the cause rather than mistaken for an app problem. Note that an extension injecting
|
||||
an <em>inline</em> script is indistinguishable from a genuine inline-script violation, so those
|
||||
are listed under “Page”.
|
||||
</p>
|
||||
|
||||
@@ -49,7 +49,7 @@ type Server struct {
|
||||
// Handler returns the root HTTP handler.
|
||||
func (s *Server) Handler() http.Handler { return s.handler }
|
||||
|
||||
// CollectCSPReports runs the violation-report writer until ctx is cancelled. Start
|
||||
// CollectCSPReports runs the violation-report writer until ctx is canceled. Start
|
||||
// it in a goroutine alongside the other background workers, and let it finish before
|
||||
// the store's pool closes — it does a final flush of anything still queued.
|
||||
func (s *Server) CollectCSPReports(ctx context.Context) { s.csp.Run(ctx) }
|
||||
@@ -57,7 +57,7 @@ func (s *Server) CollectCSPReports(ctx context.Context) { s.csp.Run(ctx) }
|
||||
// WSDrainTimeout is the recommended deadline for DrainWebSockets on shutdown. It
|
||||
// must comfortably exceed a single handler's consoleEndTimeout (the deferred
|
||||
// EndConsoleSession stamp) plus the time a handler needs to unwind after its
|
||||
// context is cancelled — otherwise the drain gives up mid-stamp and leaves the
|
||||
// context is canceled — otherwise the drain gives up mid-stamp and leaves the
|
||||
// session's ended_at NULL, so it shows "in progress" forever. It must also fit
|
||||
// inside the deployment's process stop grace (Kubernetes default 30s), alongside
|
||||
// the preceding HTTP drain. TestDrainTimeoutExceedsStamp enforces the lower bound.
|
||||
|
||||
@@ -27,9 +27,9 @@ import (
|
||||
// the connection (hijackLocked calls rwc.SetDeadline(time.Time{})), so the socket
|
||||
// inherits nothing and is bounded only by consoleIdleTimeout and the shutdown drain.
|
||||
//
|
||||
// That behaviour is load-bearing but belongs to the standard library, not to this
|
||||
// That behavior is load-bearing but belongs to the standard library, not to this
|
||||
// codebase, so it's worth an explicit test: it would catch a future WebSocket library
|
||||
// that re-arms deadlines after hijacking, or a change in Go's behaviour, either of
|
||||
// that re-arms deadlines after hijacking, or a change in Go's behavior, either of
|
||||
// which would silently start cutting console sessions mid-command.
|
||||
//
|
||||
// The server here uses a deliberately tiny 250ms ReadTimeout rather than the
|
||||
|
||||
@@ -25,12 +25,12 @@ import (
|
||||
// are resolved from CSS variables that only exist at runtime. Nothing about this is
|
||||
// checkable by reading the stylesheets.
|
||||
const contrastProbe = `(() => {
|
||||
// --- colour maths, per WCAG 2.1 -------------------------------------------------
|
||||
// Chrome serialises computed colours in more than one syntax: plain rgb()/rgba(),
|
||||
// --- color math, per WCAG 2.1 -------------------------------------------------
|
||||
// Chrome serializes computed colors in more than one syntax: plain rgb()/rgba(),
|
||||
// and color(srgb r g b / a) with 0..1 components for values that came through
|
||||
// colour-mixing or a wide-gamut source. An earlier version of this probe only
|
||||
// color-mixing or a wide-gamut source. An earlier version of this probe only
|
||||
// matched rgb() and SILENTLY SKIPPED the rest — which hid every failing link on the
|
||||
// site, since Tabler's link colour arrives in color(srgb ...) form. Anything still
|
||||
// site, since Tabler's link color arrives in color(srgb ...) form. Anything still
|
||||
// unparseable is now reported rather than ignored (see unparsed below).
|
||||
function parse(css) {
|
||||
let m = css.match(/^\s*color\(\s*srgb\s+([^)]+)\)/i);
|
||||
@@ -71,7 +71,7 @@ const contrastProbe = `(() => {
|
||||
// --- the background a pixel of text actually sits on ---------------------------
|
||||
// Walks ancestors compositing translucent layers until something opaque is found.
|
||||
// Returns null when an ancestor paints an image or gradient, since the effective
|
||||
// colour then isn't knowable from computed style alone.
|
||||
// color then isn't knowable from computed style alone.
|
||||
function backdrop(el) {
|
||||
let layers = [];
|
||||
for (let n = el; n; n = n.parentElement) {
|
||||
@@ -128,7 +128,7 @@ const contrastProbe = `(() => {
|
||||
|
||||
const fg = parse(cs.color);
|
||||
if (!fg) {
|
||||
// Never skip quietly: an unrecognised colour syntax means this element went
|
||||
// Never skip quietly: an unrecognized color syntax means this element went
|
||||
// unchecked, which is exactly how the original probe missed every link.
|
||||
unparsed.add(cs.color);
|
||||
return;
|
||||
@@ -172,9 +172,9 @@ type contrastFailure struct {
|
||||
// TestContrastMeetsWCAGAA measures real rendered contrast across the app.
|
||||
//
|
||||
// This is the check that makes shipping a single dark theme defensible: WCAG has no
|
||||
// requirement to offer two colour schemes, but it does require the one you ship to meet
|
||||
// requirement to offer two color schemes, but it does require the one you ship to meet
|
||||
// AA — 4.5:1 for body text, 3:1 for large text. That had never been verified, and the
|
||||
// stylesheet already carried a hand-picked colour added to fix a contrast problem
|
||||
// stylesheet already carried a hand-picked color added to fix a contrast problem
|
||||
// (.badge.bg-purple-lt) with nothing guarding it.
|
||||
//
|
||||
// Deliberately measured in a browser rather than read from CSS: the foreground is often
|
||||
@@ -290,7 +290,7 @@ func TestContrastMeetsWCAGAA(t *testing.T) {
|
||||
return
|
||||
}
|
||||
if len(result.Unparsed) > 0 {
|
||||
t.Errorf("%s: colour syntax the probe can't read, so those elements went "+
|
||||
t.Errorf("%s: color syntax the probe can't read, so those elements went "+
|
||||
"unchecked: %v", label, result.Unparsed)
|
||||
}
|
||||
t.Logf("%-18s %3d elements checked", label, result.Checked)
|
||||
|
||||
@@ -93,7 +93,7 @@ func (e *Exchanger) HandleData(raw []byte) {
|
||||
// retrying up to e.tries times. build receives the 1-based attempt number so it
|
||||
// can vary routing (e.g. direct early, flood as a fallback). onAttempt
|
||||
// (optional) is called before each send. Returns ErrNoReply if exhausted, or
|
||||
// ctx.Err() if cancelled.
|
||||
// ctx.Err() if canceled.
|
||||
func (e *Exchanger) exchange(ctx context.Context, build func(ts time.Time, attempt int) ([]byte, error), matchFn func([]byte) bool, onAttempt func(attempt, max int)) error {
|
||||
for attempt := 1; attempt <= e.tries; attempt++ {
|
||||
if onAttempt != nil {
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
|
||||
// RateLimiter paces transmissions within a session so we don't flood the shared
|
||||
// LoRa mesh. Each Wait reserves the next available slot spaced at least
|
||||
// `interval` apart and blocks until that slot arrives (or ctx is cancelled).
|
||||
// `interval` apart and blocks until that slot arrives (or ctx is canceled).
|
||||
//
|
||||
// It is a slot-reservation limiter rather than a leaky check: concurrent or
|
||||
// back-to-back callers queue up in order, each waiting for its own slot, so a
|
||||
@@ -25,7 +25,7 @@ func NewRateLimiter(interval time.Duration) *RateLimiter {
|
||||
}
|
||||
|
||||
// Wait blocks until this caller's send slot is reached, or returns ctx.Err() if
|
||||
// the context is cancelled first.
|
||||
// the context is canceled first.
|
||||
func (l *RateLimiter) Wait(ctx context.Context) error {
|
||||
l.mu.Lock()
|
||||
at := l.next
|
||||
|
||||
@@ -39,6 +39,6 @@ func TestRateLimiterCancelled(t *testing.T) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
cancel()
|
||||
if err := l.Wait(ctx); err == nil {
|
||||
t.Fatal("expected error from cancelled context")
|
||||
t.Fatal("expected error from canceled context")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ type CSPReport struct {
|
||||
// Deliberately excludes Sample, SourceFile, LineNumber and Hits. The sample varies
|
||||
// between otherwise identical violations (different inline snippets on the same page)
|
||||
// and the line number moves whenever a template changes, so including either would
|
||||
// shatter one problem into many rows — exactly the row-per-report behaviour the
|
||||
// shatter one problem into many rows — exactly the row-per-report behavior the
|
||||
// aggregate table exists to avoid. SourceFile is omitted as redundant: it already
|
||||
// drives Source, which IS in the fingerprint, so an extension-injected inline
|
||||
// violation and a page one on the same path are already separate rows.
|
||||
|
||||
@@ -79,7 +79,7 @@ func TestCSPReportsSeparateDistinctViolations(t *testing.T) {
|
||||
|
||||
// TestCSPReportFingerprintIgnoresSample: the sample varies between otherwise
|
||||
// identical violations, so including it would shatter one problem into many rows —
|
||||
// the row-per-report behaviour the aggregate table exists to prevent.
|
||||
// the row-per-report behavior the aggregate table exists to prevent.
|
||||
func TestCSPReportFingerprintIgnoresSample(t *testing.T) {
|
||||
t.Parallel()
|
||||
a := cspReport("script-src-elem", "inline", "/x")
|
||||
|
||||
@@ -15,7 +15,7 @@ const MaxOrgLinks = 20
|
||||
|
||||
// LinkKind classifies how a platform's value is entered, validated, stored, and
|
||||
// rendered. It replaces the per-platform switch statements the link editors used
|
||||
// to carry: behaviour is a property of the platform, looked up once here.
|
||||
// to carry: behavior is a property of the platform, looked up once here.
|
||||
type LinkKind string
|
||||
|
||||
const (
|
||||
@@ -41,7 +41,7 @@ const (
|
||||
// no custom label of its own; Icon names the "icon-*" template used by link-icon.
|
||||
//
|
||||
// For KindHandle: URLFmt is the canonical profile URL with a single %s for the
|
||||
// handle, and Hosts are the URL hosts we recognise when a user pastes a full
|
||||
// handle, and Hosts are the URL hosts we recognize when a user pastes a full
|
||||
// profile URL instead of a bare handle. Placeholder is the editor input hint.
|
||||
type LinkPlatform struct {
|
||||
Key string
|
||||
@@ -176,7 +176,7 @@ func canonicalMastodon(s string) (string, bool) {
|
||||
}
|
||||
|
||||
// hostAllowed reports whether host (case-insensitive, port stripped) is one of
|
||||
// the platform's recognised hosts.
|
||||
// the platform's recognized hosts.
|
||||
func hostAllowed(host string, hosts []string) bool {
|
||||
host = strings.ToLower(host)
|
||||
if i := strings.IndexByte(host, ':'); i >= 0 {
|
||||
|
||||
@@ -59,7 +59,7 @@ func NewCSPCollector(st *store.Store, cfg *config.Config) *CSPCollector {
|
||||
}
|
||||
}
|
||||
|
||||
// Run owns the write loop until ctx is cancelled. Start it in a goroutine. Pruning
|
||||
// Run owns the write loop until ctx is canceled. Start it in a goroutine. Pruning
|
||||
// is not done here — it's a janitor sweep (store.PruneCSPReports), alongside the
|
||||
// other expiry sweeps.
|
||||
func (c *CSPCollector) Run(ctx context.Context) {
|
||||
@@ -83,7 +83,7 @@ func (c *CSPCollector) Run(ctx context.Context) {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
// Drain what's queued (reports arriving while requests were draining),
|
||||
// then write on a fresh context since ctx is already cancelled.
|
||||
// then write on a fresh context since ctx is already canceled.
|
||||
for drained := true; drained; {
|
||||
select {
|
||||
case rep := <-c.ch:
|
||||
|
||||
@@ -585,7 +585,7 @@ func TestCrossSiteWriteBlockerExemptsReportPath(t *testing.T) {
|
||||
rec := httptest.NewRecorder()
|
||||
h.ServeHTTP(rec, req)
|
||||
if rec.Code != http.StatusNoContent {
|
||||
t.Errorf("report POST labelled cross-site got %d, want it to pass through", rec.Code)
|
||||
t.Errorf("report POST labeled cross-site got %d, want it to pass through", rec.Code)
|
||||
}
|
||||
|
||||
// The exemption must be exactly that one path — everything else still blocks.
|
||||
|
||||
@@ -178,7 +178,7 @@ func unsafeMethod(method string) bool {
|
||||
// The violation-report endpoint is exempt. Reports are POSTs the browser generates
|
||||
// itself, out-of-band from the document that triggered them, and the Sec-Fetch-Site
|
||||
// value on that delivery is not something the CSP or Reporting API specifications
|
||||
// pin down — so a report could arrive labelled "cross-site" and be silently
|
||||
// pin down — so a report could arrive labeled "cross-site" and be silently
|
||||
// discarded, leaving reporting looking merely quiet. Exempting it costs nothing:
|
||||
// the endpoint takes no session, performs no authenticated action, and its only
|
||||
// effect is incrementing a counter on an aggregate row (see CSPCollector).
|
||||
|
||||
@@ -109,7 +109,7 @@ code.pubkey {
|
||||
|
||||
/* Tabler's danger button pairs its off-white foreground (#f9fafb) with the danger red,
|
||||
which measures 4.46:1 — just under the 4.5:1 floor. Pure white reaches 4.66:1 without
|
||||
touching the button's colour. */
|
||||
touching the button's color. */
|
||||
.btn-danger {
|
||||
color: #fff;
|
||||
}
|
||||
@@ -117,7 +117,7 @@ code.pubkey {
|
||||
/* ---------- Contrast corrections (WCAG AA on the dark theme) ----------
|
||||
Found by internal/e2e TestContrastMeetsWCAGAA, which measures rendered pixels. All
|
||||
three point at Tabler's own dark-theme *-text-emphasis values rather than
|
||||
hand-picked colours, so they stay tied to the palette.
|
||||
hand-picked colors, so they stay tied to the palette.
|
||||
|
||||
Tabler's dark theme lightens --tblr-link-hover-color but NOT --tblr-link-color, which
|
||||
leaves every link at 3.55:1 on the page background and 2.94:1 on a card — below the
|
||||
@@ -127,8 +127,8 @@ code.pubkey {
|
||||
--tblr-link-color: var(--tblr-primary-text-emphasis);
|
||||
}
|
||||
|
||||
/* Inactive tab labels use --tblr-muted (#6b7280 → 3.67:1). Emphasis grey is 7.65:1 and
|
||||
still clearly dimmer than the active tab, which uses the full body colour. */
|
||||
/* Inactive tab labels use --tblr-muted (#6b7280 → 3.67:1). Emphasis gray is 7.65:1 and
|
||||
still clearly dimmer than the active tab, which uses the full body color. */
|
||||
.nav-tabs .nav-link {
|
||||
color: var(--tblr-secondary-text-emphasis);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Shared behaviour for the profile/org link editors. Both the account page and
|
||||
// Shared behavior for the profile/org link editors. Both the account page and
|
||||
// the org page render a `<form data-link-editor>` with repeatable `.link-row`s;
|
||||
// this script adds/removes rows, renumbers the primary-contact radios, adapts
|
||||
// each row to its selected platform (placeholder + whether the optional label
|
||||
|
||||
Reference in New Issue
Block a user