Skip to content

Issue 7 tak cot - #12

Open
Tom-Neverwinter wants to merge 3 commits into
bilawalsidhu:mainfrom
Tom-Neverwinter:issue-7-tak-cot
Open

Issue 7 tak cot#12
Tom-Neverwinter wants to merge 3 commits into
bilawalsidhu:mainfrom
Tom-Neverwinter:issue-7-tak-cot

Conversation

@Tom-Neverwinter

Copy link
Copy Markdown

No description provided.

Tom-Neverwinter and others added 3 commits August 25, 2026 01:02
Read-only ingest only, as scoped with the user — no Phase 2 publish-to-TAK,
no cert-upload UI. BYOS: God's Eye View never discovers or connects to a
TAK network on its own; the layer reports UNAVAILABLE unless
TAK_SERVER_HOST + a client cert/key are explicitly configured via env vars
(local file paths only, never uploaded — see SECURITY.md/.env.example).

Server: takProxy (vite.config.js) holds one mutual-TLS TCP connection
(node:tls) to the configured TAK Server, verifying the server certificate
(optionally against a private CA) and authenticating with the client
cert/key. It never sends anything onto the stream — no presence announce,
pure listen. Incoming CoT is decoded exclusively from events carrying a
usable <point> (routes/polygons/shapes are out of scope for this pass);
each object is dropped from the served snapshot the instant its own CoT
`stale` time passes. In-memory only, no disk persistence, per the issue's
"avoid persisting TAK position history" requirement.

src/data/cotEvent.js holds the pure, XML-free helpers (MIL-STD-2525
affiliation decode, staleness check) shared by server and client.
src/data/cotDecode.js isolates the XML parsing (fast-xml-parser, a new
small dependency — CoT is real, attribute-heavy, escapable XML, not worth
hand-rolling) and the TCP byte-stream event-boundary splitter
(extractCotEvents), so neither reaches the browser bundle (confirmed via
build output). src/data/takEvents.js polls the resulting snapshot and
renders points colored by affiliation.

Validated two ways beyond unit tests, since no real TAK Server was
available: (1) a genuine end-to-end run against a local self-signed
mutual-TLS server — verified client-cert auth, an event deliberately split
across two TCP writes reassembling correctly, and both a full and a
self-closing point-bearing CoT event decoding correctly; (2) the
unconfigured path's UNAVAILABLE response on a live dev server. The
specific handshake quirks of a real TAK Server implementation remain
unverified — flag this if issues surface against one.

Registered in main.js + layerState.js (token 'h'), voice/text aliases,
BYOS entry in DATA_SOURCES.md (no attribution — not public data).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GZFzxaNKiGGkq9V64Y9omb
- takEvents.js loadEvents(): never resolve `false` from update() — this is
  the critical one, since manager.js's enable-lifecycle treats a `false`
  update() as a fatal enable failure and bounces the toggle back off
  (src/data/manager.js:908-909). The layer's "not configured" branch —
  which is the DEFAULT state for this BYOS layer — was hitting exactly
  that path, so simply enabling the layer without a TAK Server configured
  never reached UNAVAILABLE; it just failed to enable at all. Also guard
  against a destroy() racing an in-flight fetch (dataSource null-deref).
- cotDecode.js: `Number('')` is 0, not NaN, so a present-but-blank CoT
  numeric attribute (e.g. `hae=""`) decoded as a fabricated 0 altitude/
  heading instead of missing. Added a regression test.
- cotDecode.js: the detail-passthrough size cap compared JS string length
  (UTF-16 code units) against a constant named for bytes; switched to
  Buffer.byteLength so a non-ASCII callsign can't slip ~2x past the
  intended budget.
- vite.config.js takProxy: renamed the buffer safety-cap constant to match
  what it actually measures (characters, not bytes) rather than silently
  fixing the discrepancy through an unwarranted per-chunk re-encoding
  cost — the cap is a coarse backstop where 2x slop doesn't matter. Also
  made the event-cache LRU eviction correct: a Map's set() on an existing
  key doesn't move it, so without delete-then-set on update, "evict the
  first key" was oldest-inserted, not oldest-seen.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GZFzxaNKiGGkq9V64Y9omb
- Security-relevant: TAK connection/cert-read errors were stored via Node's
  raw err.message and served verbatim through GET /api/tak/events — for
  common failures (ECONNREFUSED, ENOTFOUND, an fs ENOENT on the cert path)
  that message literally embeds the configured host:port or local file
  path, contradicting the documented guarantee (SECURITY.md, .env.example)
  that the browser never sees any of those. New sanitizeTakConnectionError()
  maps err.code (a stable, target-independent Node identifier) to a fixed
  generic message; the full raw detail still goes to the server's own
  console.warn log, just never crosses into the API response. Unit tested.
- ensureTakConnection() could race the reconnect backoff: a client poll
  landing in the gap between a dropped connection (_takSocket = null) and
  its scheduled 15s reconnect timer firing would trigger an immediate extra
  connect attempt — re-reading cert/key files synchronously and opening a
  second TLS handshake, roughly doubling reconnect attempts against the
  remote TAK server during an outage. Now skips if a reconnect is already
  pending.
- takEvents.js loadEvents(): add the missing response.ok check every
  sibling layer has, for the case where /api/tak/events itself returns a
  non-2xx response that isn't the deliberate "not configured" 503 shape
  (e.g. a fronting proxy in a non-dev deployment).
- Removed a dead state.viewer assignment — this layer is a global,
  non-viewport-bounded feed and never reads it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GZFzxaNKiGGkq9V64Y9omb
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.

1 participant