Skip to content

Backplane projector fix + multinode chat & Signal showcase + docs#95

Merged
joaomdsg merged 5 commits into
mainfrom
feat/showcase-and-backplane-fix
Jun 6, 2026
Merged

Backplane projector fix + multinode chat & Signal showcase + docs#95
joaomdsg merged 5 commits into
mainfrom
feat/showcase-and-backplane-fix

Conversation

@joaomdsg

@joaomdsg joaomdsg commented Jun 5, 2026

Copy link
Copy Markdown
Member

Summary

Work from this session, in four logical commits.

1. fix(applog) — projector tolerates non-contiguous per-key offsets

The event-log projector treated any offset gap (rec.Offset > cursor+1) as a
compacted prefix and halted when no bridging snapshot existed. Backends that
sequence a key's offsets from a shared space — e.g. a single NATS JetStream
stream across subjects — produce gaps that are not data loss, so the first
record of any key halted the projector and silently dropped every event. This is
the multi-log clustered case the new example/showcase apps exposed; chatcluster
(single log) never hit it.

classifyGap now separates a real compaction gap (a Compacted snapshot proves
a lost prefix → reseed or halt) from a benign non-contiguous gap (no snapshot, or
an uncompacted/unreadable one → fold), latching gapsBenign so a busy shared
stream doesn't pay a snapshot read per record. Compaction safety preserved:
only a Compacted-but-unbridgeable snapshot halts. New applognoncontiguous
tests (incl. a LoadSnapshot-counting latch test); two existing reseed tests
tightened to Compacted: true. The Offset contract (monotone, not
contiguous) is now documented in backplane.go + docs/production.md.

2. docs — backplane + showcase pages

New Distributed state Learn page and Showcase: Signal page, with
cross-links from home / why-via / reactive-state.

3. example(chatcluster) — multinode chat over the backplane

The single-node chat run as multiple nodes behind a sticky-cookie HAProxy LB with
JetStream NATS, demonstrating cross-node StateAppEvents convergence. Includes a
docker-compose stack and a tag-gated compose e2e. (Own module.)

4. feat(viashowcase) — "Signal" flagship app

A live audience platform (polls / word cloud / Q&A) exercising every plugin
(picocss, echarts, maplibre), the JetStream backplane (StateAppEvents +
OnEvent), Postgres-backed auth/profiles/avatars, cross-page theme persistence,
graceful shutdown, /healthz, and a 3-pod docker-compose deployment behind a
sticky LB. Own module (replace../, ../vianats). Includes a stored-XSS
fix in the broadcast path, crypto-random room codes, and a11y/empty-state/toast
polish.

Verification

ci-check.sh passes locally: gofmt, go vet, golangci-lint, govulncheck, build,
example builds, go test -race ./..., allocation gates. The chatcluster and
viashowcase compose e2es were run live (3-pod stacks, cross-pod convergence
confirmed). The new modules are separate (go.mod), so the root module's CI is
unaffected by their deps.

joaomdsg added 3 commits June 5, 2026 20:35
The projector treated any offset gap (rec.Offset > cursor+1) as a compacted
prefix and halted when no bridging snapshot existed. Backends that sequence a
key's offsets from a shared space (e.g. one NATS JetStream stream across
subjects) produce gaps that are not data loss, so the first record of any key
halted the projector and silently dropped every event (the multi-log clustered
case the chatcluster/viashowcase apps exposed).

classifyGap now distinguishes a real compaction gap (a Compacted snapshot proves
a lost prefix -> reseed or halt) from a benign non-contiguous gap (no snapshot,
or an uncompacted/unreadable one -> fold), latching gapsBenign so a busy shared
stream does not pay a snapshot read per record. Compaction safety is preserved:
only a Compacted-but-unbridgeable snapshot halts. Documents the
monotone-not-contiguous Offset contract (backplane.go) and a production note.
New Learn page for the state backplane (clustered StateApp/StateSess +
StateAppEvents) and a Showcase page for the Signal app, with cross-links from
home, why-via, and reactive-state.
Runs the single-node chat as multiple nodes behind a sticky-cookie HAProxy LB
with JetStream NATS, demonstrating cross-node StateAppEvents convergence. Adds a
docker-compose stack, a tag-gated compose e2e, and gitignore rules for the
nested example/showcase build outputs.
@github-actions

github-actions Bot commented Jun 5, 2026

Copy link
Copy Markdown

Dependency Review

The following issues were found:
  • ❌ 1 vulnerable package(s)
  • ✅ 0 package(s) with incompatible licenses
  • ✅ 0 package(s) with invalid SPDX license definitions
  • ⚠️ 32 package(s) with unknown licenses.
  • ⚠️ 1 packages with OpenSSF Scorecard issues.
See the Details below.

Vulnerabilities

viashowcase/go.mod

NameVersionVulnerabilitySeverity
github.com/jackc/pgx/v55.7.2Memory-safety vulnerability in github.com/jackc/pgx/v5.critical
Only included vulnerabilities with severity high or higher.

License Issues

internal/examples/chatcluster/go.mod

PackageVersionLicenseIssue Type
../../../0.0.0-00010101000000-000000000000NullUnknown License
../../../vianats0.0.0-00010101000000-000000000000NullUnknown License
github.com/CAFxX/httpcompression0.0.9NullUnknown License
github.com/andybalholm/brotli1.2.0NullUnknown License
github.com/davecgh/go-spew1.1.1NullUnknown License
github.com/klauspost/compress1.18.6NullUnknown License
github.com/kr/text0.2.0NullUnknown License
github.com/nats-io/nats.go1.52.0NullUnknown License
github.com/nats-io/nuid1.0.1NullUnknown License
github.com/pmezard/go-difflib1.0.0NullUnknown License
github.com/stretchr/testify1.11.1NullUnknown License
github.com/valyala/bytebufferpool1.0.0NullUnknown License
golang.org/x/crypto0.52.0NullUnknown License
golang.org/x/sys0.45.0NullUnknown License
gopkg.in/yaml.v33.0.1NullUnknown License

viashowcase/go.mod

PackageVersionLicenseIssue Type
github.com/jackc/pgx/v55.7.2NullUnknown License
../0.0.0-00010101000000-000000000000NullUnknown License
../vianats0.0.0-00010101000000-000000000000NullUnknown License
github.com/CAFxX/httpcompression0.0.9NullUnknown License
github.com/andybalholm/brotli1.2.0NullUnknown License
github.com/davecgh/go-spew1.1.1NullUnknown License
github.com/jackc/pgservicefile0.0.0-20240606120523-5a60cdf6a761NullUnknown License
github.com/klauspost/compress1.18.6NullUnknown License
github.com/kr/text0.2.0NullUnknown License
github.com/nats-io/nats.go1.52.0NullUnknown License
github.com/nats-io/nuid1.0.1NullUnknown License
github.com/pmezard/go-difflib1.0.0NullUnknown License
github.com/stretchr/testify1.11.1NullUnknown License
github.com/valyala/bytebufferpool1.0.0NullUnknown License
golang.org/x/crypto0.52.0NullUnknown License
golang.org/x/sys0.45.0NullUnknown License
gopkg.in/yaml.v33.0.1NullUnknown License

OpenSSF Scorecard

Scorecard details
PackageVersionScoreDetails
gomod/../../../ 0.0.0-00010101000000-000000000000 UnknownUnknown
gomod/../../../vianats 0.0.0-00010101000000-000000000000 UnknownUnknown
gomod/github.com/CAFxX/httpcompression 0.0.9 UnknownUnknown
gomod/github.com/andybalholm/brotli 1.2.0 UnknownUnknown
gomod/github.com/davecgh/go-spew 1.1.1 UnknownUnknown
gomod/github.com/klauspost/compress 1.18.6 UnknownUnknown
gomod/github.com/kr/text 0.2.0 UnknownUnknown
gomod/github.com/nats-io/nats.go 1.52.0 UnknownUnknown
gomod/github.com/nats-io/nkeys 0.4.16 🟢 5.1
Details
CheckScoreReason
Code-Review🟢 10all changesets reviewed
Maintained🟢 56 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 5
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Binary-Artifacts🟢 10no binaries found in the repo
Token-Permissions⚠️ 0detected GitHub workflow tokens with excessive permissions
Pinned-Dependencies⚠️ 1dependency not pinned by hash detected -- score normalized to 1
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
Fuzzing⚠️ 0project is not fuzzed
License🟢 10license file detected
Packaging🟢 10packaging workflow detected
Branch-Protection⚠️ -1internal error: error during branchesHandler.setup: internal error: some github tokens can't read classic branch protection rules: https://github.com/ossf/scorecard-action/blob/main/docs/authentication/fine-grained-auth-token.md
Signed-Releases⚠️ 0Project has not signed or included provenance with any releases.
Security-Policy⚠️ 0security policy file not detected
SAST🟢 5SAST tool is not run on all commits -- score normalized to 5
gomod/github.com/nats-io/nuid 1.0.1 UnknownUnknown
gomod/github.com/pmezard/go-difflib 1.0.0 UnknownUnknown
gomod/github.com/starfederation/datastar-go 1.0.3 UnknownUnknown
gomod/github.com/stretchr/testify 1.11.1 UnknownUnknown
gomod/github.com/valyala/bytebufferpool 1.0.0 UnknownUnknown
gomod/golang.org/x/crypto 0.52.0 UnknownUnknown
gomod/golang.org/x/sys 0.45.0 UnknownUnknown
gomod/gopkg.in/yaml.v3 3.0.1 UnknownUnknown
gomod/github.com/jackc/pgx/v5 5.7.2 UnknownUnknown
gomod/../ 0.0.0-00010101000000-000000000000 UnknownUnknown
gomod/../vianats 0.0.0-00010101000000-000000000000 UnknownUnknown
gomod/github.com/CAFxX/httpcompression 0.0.9 UnknownUnknown
gomod/github.com/andybalholm/brotli 1.2.0 UnknownUnknown
gomod/github.com/davecgh/go-spew 1.1.1 UnknownUnknown
gomod/github.com/jackc/pgpassfile 1.0.0 UnknownUnknown
gomod/github.com/jackc/pgservicefile 0.0.0-20240606120523-5a60cdf6a761 UnknownUnknown
gomod/github.com/jackc/puddle/v2 2.2.2 ⚠️ 2.9
Details
CheckScoreReason
Packaging⚠️ -1packaging workflow not detected
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Pinned-Dependencies⚠️ 0dependency not pinned by hash detected -- score normalized to 0
Code-Review⚠️ 1Found 5/26 approved changesets -- score normalized to 1
Binary-Artifacts🟢 10no binaries found in the repo
Maintained⚠️ 00 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 0
Token-Permissions⚠️ 0detected GitHub workflow tokens with excessive permissions
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
Security-Policy⚠️ 0security policy file not detected
Fuzzing⚠️ 0project is not fuzzed
Signed-Releases⚠️ -1no releases found
License🟢 10license file detected
Branch-Protection⚠️ 0branch protection not enabled on development/release branches
SAST⚠️ 0SAST tool is not run on all commits -- score normalized to 0
gomod/github.com/klauspost/compress 1.18.6 UnknownUnknown
gomod/github.com/kr/text 0.2.0 UnknownUnknown
gomod/github.com/nats-io/nats.go 1.52.0 UnknownUnknown
gomod/github.com/nats-io/nkeys 0.4.16 🟢 5.1
Details
CheckScoreReason
Code-Review🟢 10all changesets reviewed
Maintained🟢 56 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 5
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Binary-Artifacts🟢 10no binaries found in the repo
Token-Permissions⚠️ 0detected GitHub workflow tokens with excessive permissions
Pinned-Dependencies⚠️ 1dependency not pinned by hash detected -- score normalized to 1
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
Fuzzing⚠️ 0project is not fuzzed
License🟢 10license file detected
Packaging🟢 10packaging workflow detected
Branch-Protection⚠️ -1internal error: error during branchesHandler.setup: internal error: some github tokens can't read classic branch protection rules: https://github.com/ossf/scorecard-action/blob/main/docs/authentication/fine-grained-auth-token.md
Signed-Releases⚠️ 0Project has not signed or included provenance with any releases.
Security-Policy⚠️ 0security policy file not detected
SAST🟢 5SAST tool is not run on all commits -- score normalized to 5
gomod/github.com/nats-io/nuid 1.0.1 UnknownUnknown
gomod/github.com/pmezard/go-difflib 1.0.0 UnknownUnknown
gomod/github.com/rogpeppe/go-internal 1.15.0 🟢 4.9
Details
CheckScoreReason
Code-Review🟢 9Found 22/23 approved changesets -- score normalized to 9
Maintained🟢 57 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 5
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Packaging⚠️ -1packaging workflow not detected
Token-Permissions⚠️ 0detected GitHub workflow tokens with excessive permissions
Binary-Artifacts🟢 10no binaries found in the repo
Pinned-Dependencies⚠️ 0dependency not pinned by hash detected -- score normalized to 0
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
Security-Policy⚠️ 0security policy file not detected
Fuzzing🟢 10project is fuzzed
License🟢 10license file detected
Signed-Releases⚠️ -1no releases found
Branch-Protection⚠️ 0branch protection not enabled on development/release branches
SAST⚠️ 0SAST tool is not run on all commits -- score normalized to 0
gomod/github.com/starfederation/datastar-go 1.0.3 UnknownUnknown
gomod/github.com/stretchr/testify 1.11.1 UnknownUnknown
gomod/github.com/valyala/bytebufferpool 1.0.0 UnknownUnknown
gomod/golang.org/x/crypto 0.52.0 UnknownUnknown
gomod/golang.org/x/sync 0.20.0 UnknownUnknown
gomod/golang.org/x/sys 0.45.0 UnknownUnknown
gomod/golang.org/x/text 0.37.0 UnknownUnknown
gomod/gopkg.in/yaml.v3 3.0.1 UnknownUnknown

Scanned Files

  • internal/examples/chatcluster/go.mod
  • viashowcase/go.mod

Comment thread viashowcase/internal/ui/room_host.go Fixed
A live audience platform (polls / word cloud / Q&A) exercising every Via plugin
(picocss, echarts, maplibre), the JetStream backplane (StateAppEvents +
OnEvent), Postgres-backed auth/profiles/avatars, cross-page theme persistence,
graceful shutdown, /healthz, and a 3-pod docker-compose deployment behind a
sticky HAProxy LB. Its own module (replace -> ../, ../vianats).
@joaomdsg
joaomdsg force-pushed the feat/showcase-and-backplane-fix branch from 13b40fe to e73c7c8 Compare June 5, 2026 20:39
The broadcast script concatenated json.Marshal(title) between two raw JS
string fragments (b.textContent=…;b.style.cssText='…'), the exact shape
CodeQL's 'potentially unsafe quoting' rule flags — a crafted room title
can break out of the string and inject JS into every connected tab.

Reshape the snippet to match the established convention in push.go
(Toast) and plugins/maplibre/popups.go (ShowPopup): the title is the
sole argument of a function-call IIFE, JSON-parsed at the call site,
and consumed via b.textContent=msg (the XSS-safe DOM sink). One isolated
data segment, never dropped between two raw JS string pieces, so the
rule has nothing to flag.

Extract the builder as buildNoticeScript and assert its safety
directly in notice_internal_test.go — internal package test, justified
in the file header as a last-resort claim on a security-critical pure
function whose public-API equivalent needs DB + auth + echarts +
maplibre wired up.
@joaomdsg
joaomdsg merged commit e6ec133 into main Jun 6, 2026
6 checks passed
@joaomdsg
joaomdsg deleted the feat/showcase-and-backplane-fix branch June 8, 2026 08:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants