PROJECT WEBSITE & FIELD GUIDEDOCUMENTED BUILD / 2026.09.05.3-r1

Temporary rooms. No account required.

Keywave

Talk. Share a screen.
Stay for a game.

Keywave is a self-hosted place for a conversation. Invite a friend, bring a small group, or try Shuffle. Chat, call, draw, and share a few things without creating another account.

Calls need a compatible browser and a working relay path. Cross-browser media testing is still in progress. Read the current limits.

1:1 & small groupsPrivate rooms or consent-based Shuffle
2 MiBMaximum temporary-image size
5 / 10 / 30 / 60 sView-once display windows
No accountNo application conversation archive

01 / THE PROJECT

A few useful things
in the same room.

Start with a room link, not a profile. The tools stay with the conversation; there is no account-backed feed or message history to maintain.

Chat and calls

Text, voice, and video for two people or a small group. Each participant pair has its own cryptographic state and a safety number to compare.

Start a room ↗

Meet through Shuffle

Choose voice or video, select the room size, and consent to anonymous matching. Video matches begin with the camera off.

How matching works ↗

Show what you mean

Share a screen on a supported browser, sketch a diagram, add text or shapes, and keep talking. There is one whiteboard, opened from the call controls.

Use the shared tools ↗

Send a temporary image

JPEG, PNG, GIF, and WebP can be sent through the view-once control. Choose a display window; the normal client consumes the item after viewing.

Image formats and limits ↗

Play while you talk

Open chess, select a connected participant, and start a game. No separate invitation is required, and the board stays out of the way until opened.

Open the board ↗

Know where a call stops

Test the relay without using a camera. The local Media report separates the network path, encryption processing, and audio/video counters.

Read a media report ↗

02 / THE WIKI

Keep this page handy.

A guide for people joining a room, and for the person running the server. Start with the basics; the technical details are further down.

01 / GETTING STARTED

Create a room. Share the link.

Open Keywave and choose a one-to-one or group conversation. A room link gives someone a way to join; it is not an identity check. Share it with the people you intend to meet.

  1. Choose how to talk.Select voice or video and the room size. The documented configuration supports up to six participants.
  2. Invite the other participants.Share the room link or room ID. Keep the link private: anyone who receives it may be able to take an available place.
  3. Check your connection and safety numbers.Grant only the device permissions you need. Compare the safety number with each participant through a channel you already trust.
  4. Leave when you are done.Keywave keeps active room and reconnect state in memory. It does not provide an account-based message archive or offline delivery.

Use the same build on every device. After an update, close old Keywave tabs or reload them, then start a fresh session. The current media-binding check deliberately rejects incompatible clients.

02 / RANDOM MATCHING

Shuffle is a different way in.

Instead of sending a private invitation, Shuffle matches people waiting for the same room size. Choose the number of other people, select voice or video, confirm consent, and use Shuffle securely.

Video matches start with your camera off. Enable it when you are ready. The production profile uses authenticated TURN and relay-only ICE, so peers connect through a relay rather than being offered a direct route to each other.

Why is the consent box disabled?

The operator can turn Shuffle off with KEYWAVE_SHUFFLE_ENABLED=0. In that state, the checkbox and matching controls are intentionally disabled. Private rooms are a separate workflow; changing Nginx headers will not enable Shuffle.

Anonymous matching is not a promise of anonymity or safety. The service can still observe network metadata. Encryption does not prevent harassment, impersonation, or unwanted content. Leave an uncomfortable conversation; content policy and abuse handling remain operator responsibilities.

03 / DURING A CALL

Keep control of your camera.

Camera and microphone

Use the call controls to mute or enable devices. Camera switching selects a specific device rather than only requesting a facing direction. A denied permission or a busy device should be reported instead of silently changing your privacy choice.

Screen sharing

Start sharing with the screen control and choose a surface in the browser’s picker. Screen-only and screen-plus-camera modes are available where supported. Stopping screen-only sharing restores the camera’s previous on/off state.

The default camera filter is None. Other filters are optional. Temporary-image viewers do not use webcam filters or the former page-wide scanline effect.

Initial capture target
960 × 540 at 24 FPS
Screen + camera target
Up to 1280 × 720 at 15 FPS
Group video budget
1.8 Mb/s configured ceiling; audio and overhead are additional
Per-peer video ceiling
Up to 1.4 Mb/s, adjusted using network and encoding pressure

These are capture targets and configured ceilings, not a promise of resolution, frame rate, or latency. The browser, hardware, group size, and relay path determine the result.

Browser and mobile compatibility

The application needs HTTPS, Web Crypto, WebRTC, and compatible encoded-frame transforms on both media paths. It supports modern and legacy transform entry points, but a supported API name does not by itself prove that a call works.

Native Chrome/Chromium, Edge, LibreWolf, and phone interoperability is still being checked. Recent tests reported corrupted audio/video on some browser pairs; the latest build addresses receiver attachment order, but the supplied release record does not establish a successful physical retest. Do not rely on a blanket “works in every browser” claim. Screen-capture availability also varies by browser and device.

This project page works without JavaScript. The separate chat application requires JavaScript for signaling, encryption, and media controls.

04 / SHARING MEDIA

Images for a moment.
GIFs from a provider.

There are two separate controls. Temporary images sends a local file using the encrypted view-once workflow. The chat’s GIF button opens a provider search, not a local file picker.

TEMPORARY-IMAGE LIMITS
SettingDocumented behavior
File formatsJPEG, PNG, GIF, and WebP. Animated GIF/WebP are supported.
Maximum file size2 MiB: 2,097,152 bytes.
Display time5, 10, 30, or 60 seconds after opening.
DeliveryPairwise encrypted transfer over WebRTC data channels.
After viewingThe normal client consumes the item and removes its display resource. Transfers and waiting items have bounded lifetimes.

View once does not prevent copying. Screenshots, screen recording, another camera, a modified client, or a compromised device can retain content. Send only what you are comfortable sharing with that recipient.

GIPHY and KLIPY

The operator must configure a valid provider key before search can work. Users authorize external provider access once per session. Searches and GIF downloads go to that provider, which can see the requesting IP and search terms. An encrypted chat message does not hide that separate download.

Provider keys and empty search results

Use KEYWAVE_GIPHY_PUBLIC_API_KEY or KEYWAVE_KLIPY_PUBLIC_API_KEY. These are public web-integration keys made available to the client, not private backend credentials. No demo key is embedded.

Check the provider’s configuration, quota, authentication response, and the user’s external-content consent. The selector distinguishes an unconfigured provider from a timeout or a rejected request. Gfycat is not an implemented fallback in this build.

05 / SHARED TOOLS

Draw it. Then make your move.

The whiteboard

Open the board from the original call control. There is no second whiteboard in Tools. Draw freehand, add lines, arrows, rectangles, ellipses, and text, or select and move your objects. Color, stroke width, erasing, undo, redo, and PNG export are included.

Each participant edits their own objects. Coordinates are normalized for different screen sizes, and object counts, history, and update frequency are bounded. It is a drawing and diagramming board, not a full draw.io replacement or a persistent document editor.

Chess

Open chess in Tools, choose a connected participant, and select New game. No separate acceptance request is required. A local game is also available. Starting a remote game does not force its panel over the other person’s cameras.

The rules cover legal moves, turns, check, checkmate, stalemate, castling, en passant, and automatic promotion to a queen. The board validates move order and synchronized state. It is a casual in-call game, not a tournament service.

Board and chess updates use a separate encrypted collaboration channel. A reconnect or secure rejoin can interrupt an in-progress game or transfer; these tools do not provide durable cloud storage.

06 / SECURITY & ARCHITECTURE

What stays in the browsers.

Every participant pair establishes hybrid key material using P-256 and ML-KEM-1024. Transcript-bound HKDF-SHA-256 derives separate directional keys, and AES-256-GCM protects application content. The browser must pass its startup checks before beginning signaling.

Media uses WebRTC transport plus the application’s KW-MEDIA-2 encoded-frame protection. The current build requires paired send/receive transform binding, identified by paired-rtp-v1. Missing protection or an incompatible page is rejected rather than replaced by an unencrypted fallback.

Browser A
KeywaveSignaling & volatile room state
Browser B
Browser A
TURN relayEncrypted media & data transport
Browser B
The service coordinates the conversation; the participant browsers hold the pair keys. Rooms use a full mesh, so sending cost grows as people join.

Compare the safety numbers

Safety numbers bind the hybrid handshake to WebRTC certificate fingerprints. Compare them with the other person before trusting the connection. Repeat the comparison after a fresh session or secure rejoin. A matching room name or a green connection indicator is not an identity check.

What the service can still learn

The signaling service can observe connection addresses, timing, room membership, public handshake values, and signaling metadata. TURN sees the addresses, timing, and volume of the traffic it relays. Relay-only mode reduces direct address disclosure between peers; it does not make the infrastructure blind.

No account-backed conversation archive is implemented, but that is not the same as “no logs anywhere.” Reverse-proxy, security, hosting, and container logs are controlled by the operator. GIF providers are a separate external party.

What is outside this protection

The web origin supplies the code you run. A compromised server update, browser extension, operating system, or endpoint can undermine the design. Recipients can capture content. Safety numbers depend on people actually checking them. JavaScript is not a proven constant-time environment.

The release has local tests and a scoped engineering review, not an independent security audit, a certification, or a guarantee of post-quantum safety in every deployment. The compatibility marker is a version check, not remote-device attestation.

07 / FOR OPERATORS

Keep the app and the website separate.

This static page belongs to the project website. The calling application runs at chat.securityops.co. They have different security policies: this page needs no scripts, camera, microphone, media worker, or socket connection.

Application stack

Python/Flask and Socket.IO handle the service; gevent supplies the production runtime. The browser client and workers use JavaScript. Coturn provides authenticated relaying. Application assets and the pinned PQ vendor are self-hosted.

Reverse proxy

The documented NPM setup forwards over a private Docker network to keywave:5000, with WebSockets enabled. 127.0.0.1:5128 is retained on the host for local checks. No blanket NPM Advanced replacement is required by the updater.

Non-secret policy example

PARTIAL POLICY · NOT A COMPLETE ENVIRONMENT FILEKEYWAVE_ALLOWED_ORIGINS=https://chat.example.org
KEYWAVE_NEXT_PRODUCTION=1
KEYWAVE_PQ_REQUIRED=1
KEYWAVE_PQ_SELF_TEST=1
KEYWAVE_PQ_PARAMETER_SET=ML-KEM-1024
KEYWAVE_CLASSICAL_CURVE=P-256
KEYWAVE_MEDIA_E2EE_REQUIRED=1
KEYWAVE_ALLOW_CLASSICAL_ONLY=0
KEYWAVE_NEXT_REQUIRE_TURN=1
KEYWAVE_NEXT_REQUIRE_RELAY=1
KEYWAVE_FORCE_RELAY=1

Use your own exact HTTPS origin and separately configure authenticated TURN. Do not publish shared secrets, private keys, or a production environment file. Shuffle and provider keys remain explicit operator settings.

Updating an existing installation

The 2026.09.05.3-r1 delivery is an app-only updater for a running 2026.09.05.2 installation. It is not a standalone installer for an empty VPS. It takes the original app and dependencies from the existing local image, applies the release overlay, and exports a complete assembled source archive.

The updater checks integrity and tests, builds an isolated candidate, checks the served assets and Engine.IO, and tests authenticated relay data before cutover. It preserves the previous app container and prints a rollback command. Active conversations are interrupted during replacement.

NPM, TURN, certificates, firewall rules, unrelated hosts, and this project website are not reconfigured or restarted. Keep the old container until real calls pass. There is deliberately no “clone the newest mirror and run” command here while source synchronization is pending.

TURN and restrictive networks

A healthy HTTPS endpoint does not prove that TURN can allocate and carry data. Verify the advertised relay address, credentials, listening transport, and actual relay-port range. Test from each affected client network, not only from the VPS.

turns:host:443 is a URL, not a provisioned listener. It needs a real TURN/TLS service, a valid certificate, correct routing, and permitted access. The HTTPS reverse proxy already using port 443 does not make that port a TURN endpoint. Do not disable relay-only privacy or bypass organizational policy to make a test pass.

Read-only application checks

STATUS AND POLICY · NO CONFIGURATION CHANGEScurl --fail --show-error --max-time 15   https://chat.securityops.co/keywave-next/status

curl --fail --show-error --max-time 15   https://chat.securityops.co/keywave-next/pq-policy

These endpoints report application configuration. They do not certify a two-way call. This website never fetches them automatically.

08 / WHEN SOMETHING DOES NOT CONNECT

Follow the media, not just the status light.

A working chat socket, a relay allocation, decrypted input, decoded frames, and audible or visible playback are different checkpoints. A pass at one step does not prove the next.

WHAT TO CHECK NEXT
What you seeNext check
The page loads, but a room does not startConfirm matching client builds, startup assurance, and signaling. Check whether you are using private rooms or an intentionally disabled Shuffle control.
Signaling works, but no media path appearsUse Test relay on each affected device. It sends small synthetic data probes without activating a camera or microphone.
TURN allocates, but relay data failsCheck credentials, the advertised address, NAT mapping, and relay-port reachability. A test from the server alone may miss a client-network restriction.
Data arrives, but video is garbled or frozenDownload Media report from both ends. Compare receive-side input, processed frames, authentication failures, and decoded-frame deltas separately for audio and video.
The call asks for a fresh sessionUse Rejoin securely only when appropriate. The camera stays off until enabled. Compare new safety numbers; games or transfers may be interrupted.
A camera or screen picker does not workCheck device permission and availability. Start screen sharing from its button. A capability unavailable in that browser is not fixed by changing NPM.

Reading the report

framesDecoded is cumulative for that peer connection; its presence does not prove the video is currently moving. Current deltas and FPS matter. Unsupported statistics are reported as unknown, not fabricated zeroes.

The latest report includes mediaBindings and workerStreams. Send/receive and audio/video are separate. noKeyDropped, invalidRecord, authenticationFailed, and replayDropped help distinguish missing input from rejected encrypted records.

Share the small report, not an unrestricted log dump. The application exports bounded counters locally and does not upload them automatically. Review any file before sharing it. Never post TURN secrets, tokens, SDP, or private conversation content in a public issue.

A useful two-device acceptance test
  1. Reload both pages after the update and start a fresh two-person room without screen sharing.
  2. Enable both cameras explicitly and compare safety numbers.
  3. Confirm clear audio and moving video in both directions for at least two minutes.
  4. Switch cameras, start and stop screen sharing, and check that camera privacy is restored.
  5. Repeat on the networks people actually use. If a fault remains, collect Media report from both endpoints while it is visible.

09 / DEVELOPMENT NOTES

Which Keywave is this?

2026.09.05.3-r1Documented build · repository synchronization pending

This page describes the latest build documented in the project’s supplied release material. It does not poll the deployment or claim that a matching public tag exists. The running application’s status endpoint is the place to check its reported version.

  • 09.05.3-r1Receiver-first paired transform binding, paired-rtp-v1 compatibility, and separate audio/video worker reports. The media cipher bytes were unchanged.
  • 09.05.2-r1Retained ICE recovery work, generation-aware candidate buffering, explicit secure rejoin, and more precise recovery counters.
  • 09.05.1Relay diagnostics and authenticated bidirectional-data preflight. Revision r2 registered the missing public relay-script route.
  • 09.04.xCollaboration tools, provider GIF search, temporary animated media, layout changes, camera/screen lifecycle work, and removal of the image scanline overlay.

What has been tested

The 2026.09.05.3-r1 release record reports two complete local runs and an additional extracted-archive check. The important detail is what each test actually exercised.

APPLICATION RELEASE EVIDENCE · NOT THIS WEBSITE’S LIVE STATUS
EvidenceScope
82 Python tests per runTest doubles for upstream/Flask/Docker, plus loopback HTTP and a scripted TURN socket responder.
37 transform-binding checksProduction binding helpers with modeled native accessors and task ordering; not a physical RTP call.
348 cross-API media checksReal AES and streams with synthetic frames and transform events; not native codecs.
37 Chromium UI methodsReal DOM/canvas with mocked capture, RTC, signaling, and providers; seven viewport subtests included.
Physical media interoperabilityNot established by those tests. The native browser test was blocked in the packaging environment. Chrome/Edge/LibreWolf-to-phone and VPN/Zscaler calls require real-device validation.

Documentation basis: the release’s README.md, VALIDATION.md, SECURITY-REVIEW.md, its bundled feature source, and the earlier feature notes. Local checks are not an independent audit or a performance certification.

03 / SOURCE & CONTRIBUTIONS

Four addresses.
The same project.

The current build is ahead of the public repositories. The matching code will be committed and pushed later. Until then, use this wiki for the documented behavior and inspect each mirror’s commit history before building from it.

Bug reports are most useful with the build number, browser, affected feature, and a reviewed Media report from both ends. Send sensitive security details privately to sac@securityops.co.

These links open repository roots. No synchronized tag, release download, commit count, or live repository status is implied. The supplied application release retains GPL-3.0-only and its third-party notices.

Bring someone to the room.

Read the limits, check your connection, and start with a small conversation.

Open Keywave