@maka/maka-cli 5.199.0 → 5.200.0

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@maka/maka-cli",
3
- "version": "5.199.0",
3
+ "version": "5.200.0",
4
4
  "type": "module",
5
5
  "summary": "A command line tool for scaffolding Meteor 3.x applications using either React.",
6
6
  "description": "A command line tool for scaffolding Meteor 3.x applications using React.",
@@ -24,7 +24,7 @@ import { SAVE_VERSION } from './types/save-file.js';
24
24
  import { hubSeedRefOf } from './utilities/hub-seed.js';
25
25
  import { serializePlayer, restorePlayer, captureHubOverlay, applyHubOverlay, applyHomeBlock, writeSaveAtomic, deleteSave, restoreItem, readSave, serializeItem, saveSlug, spillPathFor, } from './utilities/persistence.js';
26
26
  import { heartbeatPresence, heartbeatPresenceNow } from './utilities/social.js';
27
- import { presenceBeatAllowed } from './utilities/presence-gate.js';
27
+ import { presenceBeatAllowed, presenceProcessOnTheStreet } from './utilities/presence-gate.js';
28
28
  import { pushSave, burnCloudSaveFor, enqueueBoundPush, flushPushQueue, writeSpill, takeLastMemorial, authToken, clearSpill, hasPendingPush, } from './utilities/cloud-saves.js';
29
29
  import { DOCWAGON_TIERS, RESUSC_FEE, DEATH_COMP } from './utilities/docwagon.js';
30
30
  import { isFence, LIFESTYLE_TIERS, LIFESTYLE_OPTIONS, canonicalLifestyleTier, canonicalLifestyleOption, lifestyleOptionAllowed, lifestyleTierFor } from './utilities/commerce.js';
@@ -823,6 +823,17 @@ export default class Game {
823
823
  holdsLiveSeat() {
824
824
  return this.ridingWith.length > 0 || this.crew.some(m => m.ghost?.liveOnly);
825
825
  }
826
+ /** Everything the presence gate judges on, in one place -- so no
827
+ * caller can answer half of it for itself (TLKZKLQ4rJBCnDjrw). */
828
+ presenceFacts() {
829
+ return {
830
+ anonymous: this._anonymous,
831
+ bench: this._bench,
832
+ hostedHub: this._hostedHub,
833
+ atHub: this.scene === this._hubScene,
834
+ holdsLiveSeat: this.holdsLiveSeat(),
835
+ };
836
+ }
826
837
  beatPresence() {
827
838
  if (!this.hasHub)
828
839
  return;
@@ -841,8 +852,11 @@ export default class Game {
841
852
  // reports, both sides of one table, twice in ten minutes.
842
853
  //
843
854
  // The rule itself lives in utilities/presence-gate.ts so it can be
844
- // tested without a Game, a hub, or a socket.
845
- if (!presenceBeatAllowed(this.scene === this._hubScene, this.holdsLiveSeat()))
855
+ // tested without a Game, a hub, or a socket -- and it is the WHOLE
856
+ // rule, account half included. `returnToHub` calls this method
857
+ // directly at every homecoming, so a gate that only guarded the
858
+ // timer-arming path was no gate at all (TLKZKLQ4rJBCnDjrw).
859
+ if (!presenceBeatAllowed(this.presenceFacts()))
846
860
  return;
847
861
  void heartbeatPresence(this.presencePayload());
848
862
  // The hub link rides the same pulse: a failed connect at boot must
@@ -861,14 +875,18 @@ export default class Game {
861
875
  */
862
876
  async pushPresenceNow() {
863
877
  // A hosted hub never dials the site from inside the site: the box's
864
- // own `maka login`, if any, is not this player's.
865
- if (this._anonymous || this._bench || this._hostedHub)
878
+ // own `maka login`, if any, is not this player's. Same predicate the
879
+ // heartbeat uses -- one account rule, one place.
880
+ if (!presenceProcessOnTheStreet(this.presenceFacts()))
866
881
  return 'offline';
867
882
  return heartbeatPresenceNow(this.presencePayload());
868
883
  }
869
884
  startPresenceHeartbeat() {
870
- if (this._anonymous || this._bench || this._hostedHub)
871
- return; // account-less, a bench, or hosted on the site: never on the street
885
+ // Account-less, a bench, or hosted on the site: never on the street,
886
+ // so don't even arm the timer. beatPresence checks this again -- it
887
+ // has to, because returnToHub beats without ever coming through here.
888
+ if (!presenceProcessOnTheStreet(this.presenceFacts()))
889
+ return;
872
890
  if (this._presenceTimer)
873
891
  return;
874
892
  this.beatPresence();
@@ -17,12 +17,37 @@
17
17
  * Game, a hub, or a socket. It is deliberately the WHOLE gate: a caller
18
18
  * that reimplements part of it inline is the bug this file exists to
19
19
  * prevent coming back.
20
+ *
21
+ * THE ACCOUNT HALF MOVED IN HERE (TLKZKLQ4rJBCnDjrw, 2026-09-15). It was
22
+ * living in Game.startPresenceHeartbeat, guarding only the process that
23
+ * ARMS the timer -- and `returnToHub` beats once directly at every
24
+ * homecoming, past that guard. So a hosted hub, a repro bench and the
25
+ * jest suite alike all dialed www.maka-cli.com on the way home with
26
+ * whatever token the BOX happened to be logged in as. In the suite that
27
+ * is the developer's own account: `loose-ends.test.ts` boots a fixture
28
+ * runner named Vex over the "Legacy Hub Fixture" seed, goes home, and
29
+ * overwrote the developer's real presence row -- so their web sheet read
30
+ * "You are on the street as Vex", a runner belonging to somebody else's
31
+ * account entirely. Two halves of one rule, in two places, is how that
32
+ * happened; both halves live here now.
33
+ */
34
+ /**
35
+ * IS THIS PROCESS ON THE STREET AT ALL? The account half of the gate --
36
+ * the half that asks whether the credentials on this box belong to the
37
+ * runner in memory. A `false` here means no beat ever, from any caller,
38
+ * at any moment; nothing downstream can re-enable it.
20
39
  */
21
- export function presenceBeatAllowed(atHub, holdsLiveSeat) {
40
+ export function presenceProcessOnTheStreet(f) {
41
+ return !f.anonymous && !f.bench && !f.hostedHub;
42
+ }
43
+ /** The WHOLE gate: the account half, then the position half. */
44
+ export function presenceBeatAllowed(f) {
45
+ if (!presenceProcessOnTheStreet(f))
46
+ return false;
22
47
  // A solo run stays private, exactly as before. Only a LIVE SEAT keeps
23
48
  // the beat alive off-hub -- the narrowest change that fixes the cut,
24
49
  // and at that point other real players are sitting at the table, so
25
50
  // "the run is nobody's business" no longer describes the situation.
26
- return atHub || holdsLiveSeat;
51
+ return f.atHub || f.holdsLiveSeat;
27
52
  }
28
53
  //# sourceMappingURL=presence-gate.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@maka/maka-cli",
3
- "version": "5.199.0",
3
+ "version": "5.200.0",
4
4
  "type": "module",
5
5
  "summary": "A command line tool for scaffolding Meteor 3.x applications using either React.",
6
6
  "description": "A command line tool for scaffolding Meteor 3.x applications using React.",