sailkick-boat 0.21.2 → 0.21.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -242,6 +242,15 @@ so the boat's own app opens with no password, fully offline. Everything else in
242
242
  config passes through untouched. (Hand-edit `proxy.openAccess: false` to keep the cloud
243
243
  login gate — there is no toggle, since the gate cannot complete over the mirror anyway.)
244
244
 
245
+ It also fills in **`boat.perfKey`**, which the cloud only sends to a logged-in session.
246
+ Without it the app has no identity and the **performance data cloud** — the recorded
247
+ (TWA, STW) samples behind the polar plot, baked to `/perf/<perfKey>/estimate.json` — never
248
+ loads, even though the bake itself is cached and reachable. The key is derived rather than
249
+ configured: the app server takes a boat's Influx bucket and its perf directory from the
250
+ same identity, so the bucket minus its `_raw` suffix *is* the perf key, for a UUID account
251
+ and a grandfathered slug one alike. An unpaired boat has no bucket, so `boat` is left
252
+ exactly as the cloud sent it.
253
+
245
254
  ## Routes, polars and settings — stored on the boat
246
255
  The app reads and writes these through `/api/profile/*`. On the cloud that router is
247
256
  session-gated, and the mirror can never satisfy it: the caching GET path forwards no
package/index.js CHANGED
@@ -266,9 +266,17 @@ module.exports = function (app) {
266
266
  if (upstream.ignored) {
267
267
  ;(app.error || console.error)(`[sailkick-boat] ignoring proxy.sailkickUrl "${upstream.ignored}" left over from an older config — mirroring ${upstream.url}. Set proxy.selfHosted:true to keep your own server.`)
268
268
  }
269
+ // Boat identity for the app, derived — never guessed. The cloud only fills
270
+ // config.boat for a logged-in session and the mirror forwards no cookie, so the app
271
+ // ran with no identity and public/engine/polar-cloud.js could not find its data
272
+ // cloud (it keys on boat.perfKey). The app server defaults `bucket` and `perfKey`
273
+ // from the same identity (server/auth/registry.js), so the bucket minus its _raw
274
+ // suffix IS the perf key — for a UUID account and a grandfathered slug one alike.
275
+ const perfKey = b && b.bucket ? String(b.bucket).replace(/_raw$/, '') : null
269
276
  const pOpts = {
270
277
  sailkickUrl: upstream.url,
271
278
  storeDir: store,
279
+ boat: perfKey ? { perfKey, slug: (b && b.slug) || perfKey } : null,
272
280
  proxyPort: (proxyPort = p.proxyPort == null ? 8080 : p.proxyPort),
273
281
  localSignalkUrl: p.localSignalkUrl || 'http://127.0.0.1:3000',
274
282
  localPaths: (p.localPaths && p.localPaths.length) ? p.localPaths : PROXY_TUNING.localPaths,
@@ -93,9 +93,11 @@ function createProxy (app, options) {
93
93
  history: options.history || null,
94
94
  aisTargets: options.aisTargets || null,
95
95
  profile: options.profile || null,
96
+ boat: options.boat || null, // { perfKey, slug } — patched into /api/config, see serveConfig
96
97
  openAccess: options.openAccess !== false
97
98
  }
98
99
  log(`mirroring ${cfg.upstream}; local SignalK ${cfg.localSignalk}; store ${cfg.storeDir}`)
100
+ if (cfg.boat && cfg.boat.perfKey) log(`boat identity for the app: perfKey=${cfg.boat.perfKey} (performance data cloud at /perf/${cfg.boat.perfKey}/)`)
99
101
 
100
102
  // Cache-manifest poller: auto-refresh a dataset lazily when the cloud
101
103
  // announces a new bake. Tiles are otherwise pinned (no time-based expiry).
@@ -293,6 +295,26 @@ function createProxy (app, options) {
293
295
  if (j && typeof j === 'object') {
294
296
  j.auth = { ...(j.auth || {}), required: false } // single-tenant boat: no cloud login
295
297
  if (cfg.history && cfg.history.available()) j.historyAvailable = true // served locally (InfluxDB or ring)
298
+ // The cloud fills `boat` only for a logged-in session, and the mirror forwards no
299
+ // cookie — so it always arrived as null and the app had no identity. Harmless for
300
+ // most of the UI, but public/engine/polar-cloud.js keys the performance data cloud
301
+ // on boat.perfKey and throws 'no boat identity' without it, so the polar cloud was
302
+ // simply absent on the boat while the bake sat cached and reachable.
303
+ //
304
+ // perfKey is not guessed: server/auth/registry.js defaults `bucket` and `perfKey`
305
+ // from the same identity, so the bucket minus its _raw suffix IS the perf key —
306
+ // for UUID accounts and for grandfathered slug ones alike.
307
+ if (cfg.boat && cfg.boat.perfKey) {
308
+ j.boat = {
309
+ ...(j.boat || {}),
310
+ perfKey: cfg.boat.perfKey,
311
+ slug: cfg.boat.slug || cfg.boat.perfKey,
312
+ name: (j.boat && j.boat.name) || cfg.boat.slug || cfg.boat.perfKey,
313
+ // NEVER readOnly: that flag exists for public visitor sessions, and it hides
314
+ // the editing affordances. The owner at the chart table has full control.
315
+ readOnly: false
316
+ }
317
+ }
296
318
  out = Buffer.from(JSON.stringify(j))
297
319
  ct = 'application/json'
298
320
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sailkick-boat",
3
- "version": "0.21.2",
3
+ "version": "0.21.3",
4
4
  "description": "Run the sailkick app on board with no internet: charts, weather, climatology, trends and AIS all served from the boat itself. With a sailkick account it also syncs your metrics to the cloud in real time. Alpha, invite-only \u2014 info@sailkick.io",
5
5
  "main": "index.js",
6
6
  "scripts": {