PageSourceSearch

https://app.replicants.ai/js/spaces-entitlement.js?v=20261004sst1

js replicants.ai collected 2026-10-05 12:30:49 UTC 3,419 bytes, 68 lines download raw bytes

1/* src/public/js/spaces-entitlement.js — THE ONE SPACES ENTITLEMENT RULE
2 * (R12-SPACES-STUDIO, Alex 4 Oct 2026).
3 *
4 * Alex: "we currently have courses, games, and challenges already in the plan…
5 * for free community customers… We don't take any of those features away but
6 * Spaces becomes a paid product that you need to be on the Studio plan for."
7 *
8 * Loaded by the coach app as a plain script (window.SpacesEntitlement) AND
9 * required by the server (src/services/spaces-beta.js), so the client, the
10 * server and the member site all ask exactly this function. Nothing else
11 * decides it; nothing re-derives it.
12 *
13 * THE RULE, on a features object:
14 *
15 *   features.spaces !== true                         → 'none'    (no beta)
16 *   features.spaces === true AND
17 *     (features.spaces_override === true             → 'open'    (an admin tester)
18 *      OR studio)                                    → 'open'    (Studio + beta)
19 *   features.spaces === true, no Studio, no override → 'frozen'
20 *
21 *  · `features.spaces` is THE beta key, written only by spaces-beta.setSpacesBeta()
22 *    (R12-SPACES-FUNNEL's one writer): the admin switches, and the Stripe webhook
23 *    when a coach pays through Peter's Studio link.
24 *  · `features.spaces_override` is the admin's "Spaces without Studio" tick-box
25 *    (feature-registry.js). Migration 952 set it for every account that held the
26 *    beta before this rule, and for the owner of our own coaches' community, so
27 *    nobody testing today loses Spaces.
28 *  · `studio` is NOT a stored flag. The server works it out from the plans the
29 *    business holds (live-allowance.hasStudio: the `platform` plan, through the
30 *    one shared entitlement predicate) and hands the coach app the answer as
31 *    `features.spaces_studio` on the COPY of features it is shown at sign-in,
32 *    exactly as courses and the lifetime website are overlaid. Never written.
33 *
34 * 'frozen' is the downgrade state: the coach's spaces stay where they are and
35 * their members keep reading what they bought, but the coach cannot create or
36 * edit and nothing new is sold or started (docs/projects/spaces-studio/BUILD.md §4).
37 */
38(function (root, factory) {
39  var api = factory();
40  if (typeof module === 'object' && module.exports) module.exports = api;
41  else root.SpacesEntitlement = api;
42}(typeof self !== 'undefined' ? self : this, function () {
43  'use strict';
44
45  function _features(x) {
46    var o = (x && typeof x === 'object') ? x : {};
47    return (o.features && typeof o.features === 'object') ? o.features : o;
48  }
49
50  /**
51   * @param {object} featuresOrCustomer  a features object, or a row carrying one
52   * @param {boolean} [studio]  does the business hold Studio? When omitted, the
53   *   coach app's overlaid `features.spaces_studio` answers.
54   * @returns {'open'|'frozen'|'none'}
55   */
56  function state(featuresOrCustomer, studio) {
57    var f = _features(featuresOrCustomer);
58    if (f.spaces !== true) return 'none';
59    if (f.spaces_override === true) return 'open';
60    var s = (typeof studio === 'boolean') ? studio : (f.spaces_studio === true);
61    return s ? 'open' : 'frozen';
62  }
63
64  function open(featuresOrCustomer, studio) { return state(featuresOrCustomer, studio) === 'open'; }
65  function frozen(featuresOrCustomer, studio) { return state(featuresOrCustomer, studio) === 'frozen'; }
66
67  return { state: state, open: open, frozen: frozen };
68}));

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.